L’archiviazione delle password è una delle poche aree del software in cui esiste una risposta davvero corretta, pubblicata, mantenuta e gratuita. È anche una di quelle che si sbagliano con maggiore costanza, perché le risposte sbagliate a un certo punto erano giuste e nessuno le ha più riviste.

Il fallimento è raramente esotico. È un sistema costruito nel 2016 seguendo indicazioni che erano attuali nel 2012, che gira ancora, che accetta ancora login, e nella cui funzione di hashing nessuno mette più il naso da quando la persona che l’aveva scritta se n’è andata.

Se dovete portarvi via una cosa sola: usate Argon2id, e se non potete, usate bcrypt. Tutto il resto di questo articolo è dettaglio. Una funzione hash generica come SHA-256 non è un hash per password, per quante volte la applichiate, perché la sua velocità è un obiettivo di progetto, e la velocità è esattamente ciò che state cercando di negare a un attaccante che ha in mano il vostro database.


L’archiviazione delle password ha una sola forma corretta

Salvate un hash prodotto da una funzione deliberatamente lenta e avida di memoria, con un salt casuale univoco per ogni password, usando parametri tarati sul vostro hardware.

La guida OWASP sull’archiviazione delle password enuncia con precisione le raccomandazioni attuali, e vale la pena citarle come numeri invece che come principi.

AlgoritmoParametri consigliatiQuando usarlo
Argon2id19 MiB di memoria, 2 iterazioni, 1 grado di parallelismoPrima scelta
scryptN=2^17 (128 MiB), r=8, p=1Se Argon2id non è disponibile
bcryptWork factor 10 o superiore, limite di 72 byte per passwordSistemi legacy
PBKDF2-HMAC-SHA256600.000 iterazioniDove serve la conformità FIPS-140

Due note su quella tabella. Il valore di Argon2id è un minimo, e più memoria con meno iterazioni è uno scambio equivalente, tanto che una configurazione da 47 MiB con 1 iterazione offre una sicurezza paragonabile alla linea di base. E il limite di 72 byte di bcrypt è un troncamento vero, non una regola di validazione: tutto ciò che supera i 72 byte viene ignorato in silenzio, il che conta se accettate passphrase lunghe o se pre-calcolate l’hash dell’input.

Questi parametri vengono rivisti man mano che l’hardware migliora. Quando implementate, leggete la fonte e non questa tabella.

Un salt non è facoltativo e non è sufficiente

Un salt è un valore casuale univoco memorizzato accanto a ogni hash. Il suo scopo è ristretto e importante: garantisce che due utenti con la stessa password producano hash diversi, il che manda a vuoto le rainbow table precalcolate e impedisce a un attaccante di violare una sola password e ottenere ogni account che la condivideva.

Quello che un salt non fa è rallentare qualcuno. Un attaccante che ha il vostro database ha anche i salt, perché devono essere leggibili per verificare un login. Salare soltanto, contro un hash veloce, significa che l’attaccante aggredisce ogni password singolarmente a velocità enorme, che è esattamente la situazione che volevate evitare.

La lentezza deve venire dall’algoritmo. È tutto il senso di una funzione avida di memoria: consuma risorse di proposito, così che un attaccante con hardware specializzato guadagni molto meno vantaggio di quanto ne otterrebbe contro un hash veloce.

Un pepper, un valore segreto applicato a ogni password e conservato fuori dal database, aggiunge uno strato reale, perché il solo dump del database non basta più. Aggiunge anche un carico operativo, dato che ruotarlo impone di ricalcolare l’hash al login successivo, e perderlo blocca fuori ogni account. Ne vale la pena per i sistemi di alto valore, e per la maggior parte si può saltare.

Gli errori che sopravvivono per anni

Un hash veloce con un salt. SHA-256 con un salt sembra responsabile e non lo è. La velocità è la vulnerabilità.

Cifratura invece di hashing. La cifratura è reversibile per progetto, quindi esiste una chiave, e chiunque la ottenga ottiene ogni password in chiaro. Le password non devono mai essere recuperabili, solo verificabili.

Work factor impostati una volta e mai alzati. Un costo bcrypt scelto nel 2015 è sensibilmente più debole contro l’hardware del 2026. Alzatelo al login riuscito successivo, quando avete il testo in chiaro per un istante e potete ricalcolare l’hash.

Troncamenti o restrizioni sui caratteri. Una lunghezza massima sotto i 64 caratteri circa, o il divieto di certi caratteri, di solito segnala che la password viene conservata in un modo a cui interessa il suo contenuto. Non dovrebbe interessargli: la state passando a una funzione di hash.

Un confronto che perde informazione dal tempo. La verifica deve usare un confronto a tempo costante. Le funzioni delle librerie standard lo fanno, i controlli di uguaglianza scritti a mano no.

Registrare la password nei log. Finisce in un log di errore, in una traccia di richiesta o in un sistema di monitoraggio, e a quel punto sta in tre posti con controlli di accesso più deboli di quelli del database.

Migrare un sistema esistente

Non potete ricalcolare l’hash di ciò che non avete, perché possedete solo hash. L’approccio praticabile è aggiornare al login.

Quando un utente si autentica con successo, avete la sua password in chiaro in memoria per un istante. Verificatela contro il vecchio hash, poi calcolatene subito uno nuovo con l’algoritmo corrente e sostituite il valore memorizzato. Nell’arco di qualche mese la maggior parte degli account attivi migra senza alcun cambiamento visibile per l’utente.

Tracciate l’algoritmo record per record così che i due possano convivere, e fissate una data oltre la quale i vecchi hash rimasti vengono invalidati e quegli utenti devono reimpostare la password. Gli account dormienti con hash deboli sono esattamente quelli che un attaccante vuole.

Non incapsulate il vecchio hash dentro il nuovo algoritmo come scorciatoia. Funziona, e lascia l’hash debole come confine di sicurezza effettivo mentre tutto sembra moderno.

Cosa conta più dell’algoritmo

Un hashing corretto vi protegge quando il database esce. Non fa nulla contro l’attacco più comune, cioè qualcuno che accede con una password vera ottenuta altrove.

Il rate limiting sull’autenticazione, la disponibilità del multifattore, il confronto delle nuove password con gli elenchi di credenziali già violate e gli avvisi sui pattern di credential stuffing affrontano proprio questo, e contano tutti più nel quotidiano della scelta tra Argon2id e bcrypt. I controlli di sicurezza delle API appartengono alla stessa famiglia di problemi.

Entrambe le cose vanno fatte, e sull’ordine conviene essere onesti: sistemate l’hashing una volta perché è economico e permanente, poi spendete lo sforzo continuo sul percorso di login, che è dove gli attacchi arrivano davvero. Mecanik esamina entrambi nell’ambito della nostra analisi di sicurezza delle applicazioni.



Domande frequenti

Qual è il miglior algoritmo di hashing per password nel 2026? Argon2id, con almeno 19 MiB di memoria, 2 iterazioni e 1 grado di parallelismo. Se non è disponibile, scrypt con N=2^17, r=8, p=1 è un’alternativa, bcrypt con un work factor di 10 o superiore va bene per i sistemi legacy, e PBKDF2-HMAC-SHA256 a 600.000 iterazioni copre i requisiti FIPS-140.

Basta salare le password? No. Un salt garantisce che password identiche producano hash diversi, manda a vuoto le rainbow table ed evita che una sola password violata apra ogni account che la condivideva. Non rallenta l’attaccante, perché i salt devono essere leggibili per verificare i login. La lentezza deve venire da un algoritmo deliberatamente avido di memoria.

Perché non usare SHA-256 per le password? Perché la sua velocità è un obiettivo di progetto, e la velocità è esattamente ciò che state cercando di negare a un attaccante che ha il vostro database. Una funzione hash generica non è un hash per password, a prescindere da quante volte venga applicata o dal fatto che sia salata.

bcrypt ha un limite di lunghezza per le password? Sì, 72 byte, e tutto ciò che va oltre viene troncato in silenzio invece che rifiutato. Conta se accettate passphrase lunghe o se pre-calcolate l’hash dell’input prima di passarlo a bcrypt, dato che il troncamento avviene senza alcun errore che lo segnali.

Come aggiorno gli hash delle password senza avere le password degli utenti? Al login. Quando un utente si autentica avete il suo testo in chiaro per un istante, quindi verificate contro il vecchio hash e ricalcolate subito con l’algoritmo corrente. Tracciate l’algoritmo record per record così che i due convivano, e fissate una data oltre la quale i vecchi hash rimasti vengono invalidati e quegli utenti devono reimpostare la password.