Per rafforzare un hash per le password, devi fare due cose nel processo di hashing:
- per renderlo unico;
- per rallentare.
"Unico" significa che ogni password deve essere sottoposta a hash con la propria funzione di hash; quale hash è usata può essere qualche informazione pubblica (cioè memorizzata lungo il valore hash), ma tu vuoi renderla diversa per ogni password che hai. Questo è ciò che fa salt : il sale definisce la procedura di hash da utilizzare, tra una famiglia ampia. L'unicità sconfigge le tabelle arcobaleno: le tabelle arcobaleno, come tutti gli altri tipi di tabelle precalcolate, si basano sull'idea che valga la pena passare un po 'di tempo a digitare un sacco di password e memorizzare i valori hash (possibilmente in modo intelligente che consente una compressione estrema , come le tabelle arcobaleno), perché la tabella risultante può essere utilizzata per attaccare diverse password, con un costo marginale per password molto piccolo. Con i sali, ogni password ha una sua funzione, quindi la tabella è valida solo per una sola password, il che ne distrugge i vantaggi.
Hashing "1000 (o più) volte" la password non include un salt, e, come tale, è vulnerabile alle tabelle precalcolate. Ad esempio, supponendo SHA-256 come funzione hash, ecco la tua password con hash:
f3f19029aa4ef4bde723f49b4e90a7ad51473c54a03589af6fef706bf50d7894
Questo è l'hash SHA-256 di 1000 caratteri "a". Potrei precomprimere quel valore perché una volta che hai detto "1000" hai detto tutto; niente sale, quindi nessuna sorpresa per l'aggressore.
Lentezza significa rendere ogni password indovina il più costoso possibile per l'attaccante. Anche con una buona salatura, una singola password con hash può essere vulnerabile alla forza bruta, ovvero " attacco di dizionario " (cercando potenziali password), perché gli umani non sono così fantasiosi quanto i computer sono potenti. Un PC con una GPU può calcolare una funzione hash un miliardo di volte al secondo. Vogliamo una procedura di hashing che richiede più tempo per il calcolo - non troppo, perché il nostro server onesto avrà anche le password di hash quando un utente effettua il login e non abbiamo neanche una CPU infinita; ma abbiamo solo bisogno di hash, al massimo, una dozzina di password al secondo, quindi possiamo tollerare una funzione hash sostanzialmente lenta.
Solitamente, la lentezza si ottiene imponendo l'hashing nidificato: abbiamo cancellato la password, quindi abbiamo cancellato il valore hash risultante, che abbiamo nuovamente cancellato e così via. Ci sono alcuni dettagli complicati su come e dove viene inserito il sale. Hashing della concatenazione di 1000 volte (in realtà, con le cifre sopra, 1 milione di volte sarebbe meglio) la password (o la concatenazione della password e del sale) potrebbe servire allo stesso scopo, ma è un po 'delicato in pratica: infatti, vogliamo configurare il numero di ripetizioni della password in modo che la procedura sia tollerabilmente lenta. Ma con un tale sistema, l'hashing di una password di 40 caratteri richiede 40 volte il tempo di hashing di una password di 1 carattere; se quest'ultimo deve essere lento, il primo sarà 40 volte più lento, il che diventa presto intollerabile. Con l'hashing nidificato, è più semplice ottenere un tempo di hashing costante, che semplifica la configurazione.
E, naturalmente, fatto in casa è Bad . Inserire una password e un sale in una funzione hash, iterata e / o annidata, è sottile; ci sono insidie e, peggio di tutto, non puoi sapere se hai sbagliato o no. La sicurezza non può essere verificata in modo affidabile. Pertanto, dovresti rispettare gli standard di buona reputazione pubblicati e ampiamente implementati, come bcrypt e PBKDF2 . Se solo perché significa che qualsiasi contrattempo non sarà il tuo difetto.