Un sito fatto bene non sa la tua password. Non è che non voglia saperla: è che non può.
Sembra una furbizia, perché ogni volta che la scrivi il sistema ti fa passare, e per farti passare deve pur verificare qualcosa. Ma verificare non è sapere. Il server conserva un’impronta calcolata a partire dalla tua password; quando la scrivi, ricalcola l’impronta e confronta. Se coincidono, avanti. In nessun momento serve che la password sia scritta da qualche parte.
Da qui esce il segnale più netto per distinguere un servizio serio da uno che non lo è: se quando la dimentichi te la rispediscono per email, ce l’avevano conservata. E ciò che è conservato finisce, prima o poi, nelle mani di qualcun altro.
1979 l’idea di non conservarle — e quella di farlo piano
Nel 1979, Robert Morris e Ken Thompson pubblicarono su Communications of the ACM «Password Security: A Case History», raccontando quello che avevano fatto in Unix. È il resoconto di una lezione imparata, e dentro ci sono due idee che oggi diamo per scontate.
La prima non l’hanno inventata loro —conservare l’hash invece della password si faceva già prima—, ma l’hanno spiegata meglio di chiunque altro: non conservare la password, conservare il suo hash. Una funzione che trasforma la tua password in un valore dall’aspetto arbitrario e che non si può ripercorrere all’indietro: dall’hash non si torna alla password.
La seconda è loro: il salt. Un valore casuale diverso per ogni utente, che si mescola alla password prima di calcolare l’hash. Senza salt, due persone con la stessa password hanno lo stesso hash —il file rubato diventa un gioco di trova le coppie— e, peggio, qualcuno può precalcolare una tabella gigantesca una volta sola e usarla contro tutti i database del mondo. Il salt non rende la tua password più difficile da indovinare: fa sì che indovinarla non serva a nessun altro.
Ma in quello stesso articolo c’è una terza idea, molto meno citata, ed è quella che conta qui: hanno reso la funzione deliberatamente lenta. Non per distrazione. Di proposito. Cifrare una password costava molto più di quanto tecnicamente servisse, perché a chi entra una volta ogni mattina non cambia niente, e a chi prova milioni di candidate sì.
Ecco tutta la faccenda in una frase di quasi cinquant’anni fa.
Perché la lentezza è l’unica difesa onesta
Quasi tutte le difese informatiche sono asimmetriche: costano poco a chi si difende e molto a chi attacca. Cifrare è economico; decifrare senza la chiave è impraticabile. Chi difende gioca con un vantaggio strutturale.
L’archiviazione delle password no. Qui difensore e attaccante eseguono esattamente la stessa funzione. Tu calcoli l’hash per verificare di averci azzeccato; lui lo calcola per verificare se ci ha azzeccato. È l’unica gara della sicurezza in cui i due corrono con le stesse gambe.
Quando non puoi correre più forte del tuo rivale, resta una sola mossa: rendere la pista più cara per entrambi. Tu paghi quel costo una volta per accesso. Lui, una volta per tentativo. Siccome gli servono ordini di grandezza più tentativi che a te, lo stesso conto vi colpisce in modo incomparabile. È questo che fa un hash di password.
Per questo le funzioni veloci e ottime per altre cose —SHA-256, per esempio— sono una scelta pessima qui. Sono veloci. Veloce è esattamente ciò che non vogliamo.
1999 bcrypt, e il costo come pezzo regolabile
Il problema di una funzione lenta è che l’hardware non sta fermo. Quello che nel 1979 era lento, dopo è istantaneo. Una difesa tarata sui computer di un decennio invecchia da sola, senza che nessuno la tocchi.
Nel 1999, Niels Provos e David Mazières presentarono bcrypt alla USENIX Annual Technical Conference, con un titolo che dice già tutto: A Future-Adaptable Password Scheme.
L’idea: che il costo non stia nella funzione, ma in un parametro. bcrypt porta con sé un fattore di costo che decidi tu e che viene conservato insieme all’hash. Se l’hardware diventa molto più veloce, alzi il numero e le password nuove tornano a costare quello che devono, senza cambiare algoritmo.
È un progetto che dà per scontata la propria obsolescenza e si prepara ad essa. C’è pochissimo software che lo faccia.
2009 scrypt, e la scoperta che il tempo non basta
bcrypt rende caro il tempo di calcolo, e ha funzionato. Finché l’attaccante non ha smesso di usare lo stesso tipo di macchina del difensore.
Un server ha pochi core veloci e generalisti. Una GPU ha una quantità assurda di core piccoli che fanno la stessa cosa in parallelo, e un ASIC va oltre: silicio fabbricato per eseguire una sola operazione. Se la tua difesa consiste nel «questa operazione costa X», qualcuno può costruire hardware che faccia molte X in una volta. Il difensore resta lì con il suo server.
Nel 2009, Colin Percival presentò scrypt con un altro argomento: Stronger Key Derivation via Sequential Memory-Hard Functions. Se il costo sta solo nel calcolo, si parallelizza. Ma la memoria non te la regala nessuno. Obbliga la funzione a usare molta RAM e a percorrerla in un modo che non si può aggirare, e di colpo l’attaccante non può moltiplicare i core: ogni core avrebbe bisogno della propria memoria. E i core di una GPU hanno tanta potenza e pochissima RAM a testa.
Percival non ha reso cara l’operazione. Ha reso caro l’hardware necessario per ripeterla in massa. È un cambio di livello: si attacca il budget dell’attaccante, non il suo orologio.
2015 Argon2, e la fine del dibattito
Che esistessero varie opzioni ragionevoli non aiutava nessuno a scegliere. Così la comunità crittografica ha fatto quello che fa di solito quando vuole chiudere una questione: un concorso pubblico. La Password Hashing Competition ha ricevuto candidati, li ha sottoposti ad analisi aperta per anni e nel 2015 ha proclamato vincitore Argon2.
Argon2 eredita le due lezioni: costo in tempo e costo in memoria, entrambi regolabili separatamente, più il numero di thread. Non è magia. È la sintesi ordinata del 1979, del 1999 e del 2009, rivista da gente il cui lavoro consisteva nel provare a romperla.
Cosa significa questo per te
Quasi niente di tutto ciò è nelle tue mani, ed è giusto dirlo: l’hash lo sceglie il sito, non tu. Puoi avere la password migliore del mondo e vedertela conservare in chiaro dentro un Excel.
Ma l’altro lato dell’equazione dipende da te. Tutto questo edificio —il salt, il costo, la memoria— serve a rendere caro ogni tentativo dell’attaccante. Quello che decide quanti tentativi gli servono è la tua password. Se sta in un dizionario, nessuna funzione lenta ti salva: cadrà tra le prime. Se è lunga e non somiglia a niente, quel prezzo per tentativo si moltiplica per un numero di tentativi che non ci sta nel tempo disponibile.
Per questo il nostro generatore misura bit di entropia e non percentuali, e per questo il controllo cerca la tua password nei dizionari prima di contare i simboli. Loro mettono il prezzo per tentativo; tu metti il numero di tentativi. Nessuna delle due metà funziona senza l’altra.
E sì: resta la stessa domanda di sempre. Solo che adesso, dall’altra parte, qualcuno prova a rispondere molte volte al secondo, e dal 1979 stiamo cercando di fare in modo che ognuna di quelle volte gli costi soldi.
Fonti: R. Morris e K. Thompson, «Password Security: A Case History», Communications of the ACM, 1979 · N. Provos e D. Mazières, «A Future-Adaptable Password Scheme», USENIX Annual Technical Conference, 1999 (bcrypt) · C. Percival, «Stronger Key Derivation via Sequential Memory-Hard Functions», 2009 (scrypt) · Password Hashing Competition, vincitore Argon2, 2015.