Memoria / uso corretto delle password salate?

3

Se un sale non viene memorizzato insieme alla password hash nel database, è possibile che la password sia salata?

Chiedo perché in un sistema su cui sto lavorando c'è solo una colonna di password, ma quando ripasso il codice sembra che chiunque abbia scritto questo stia tentando di salare la password.

Da quello che ho capito, password e sali dovrebbero essere archiviati come di seguito:

email         | password (hashed)        | salt (not hashed)
[email protected] | de898928393a893sfe7f98s7 | S#ne3

Quindi, quando un utente si è registrato con la propria password ("froggy" nell'esempio seguente) sarebbe andata più o meno così:

//Generate salt (S#ne3 for this example)
//encrypt ("froggy" + "S#ne3")
//Save encrypted pw + salt to database AND save unencrypted salt to database

Quindi, quando l'utente ha tentato di accedere con "froggy", sarebbe andato in questo modo:

//Query database for user's record.  Store this in curUser object
//Check to see if the following match: encrypt("froggy" + curUser.salt) == curUser.password

Suona bene? Se ho ragione, è sicuro assumere che le password su questo sistema non siano salate?

    
posta Abe Miessler 17.08.2013 - 01:03
fonte

3 risposte

3

Prima di tutto, le password sono memorizzate in modo sicuro (presupponendo che l'algoritmo di hashing utilizzato sia sicuro) poiché l'unica cosa in chiaro è il sale che deve essere in chiaro: il suo unico scopo è impedire che l'hash finale sia hash(password) dal ciò consentirebbe l'utilizzo di tabelle arcobaleno precalcolate che associano gli hash alle password.

Tuttavia, il modo di archiviarli usando due colonne separate non è ottimale. Sebbene sia piuttosto facile da usare quando si passa la password salt e plaintext a una funzione hash, la maggior parte delle librerie di hashing delle password utilizzano uno schema migliore. Diamo un'occhiata a bcrypt (o meglio ai suoi collegamenti Python per semplicità) che usa lo stesso schema di crypt(3) fa.

>>> import bcrypt
>>> bcrypt.gensalt()
'$2a$12$xYkBJKIdbmAZlhpl96dopO'
>>> bcrypt.hashpw('foo', '$2a$12$xYkBJKIdbmAZlhpl96dopO')
'$2a$12$xYkBJKIdbmAZlhpl96dopOJug5oZcp4tVWJPug/xMdFQzVMJDOvH6'
>>> bcrypt.hashpw('foo', '$2a$12$xYkBJKIdbmAZlhpl96dopOJug5oZcp4tVWJPug/xMdFQzVMJDOvH6')
'$2a$12$xYkBJKIdbmAZlhpl96dopOJug5oZcp4tVWJPug/xMdFQzVMJDOvH6'

Come puoi vedere, l'hash risultante è costituito da parti multiple . Innanzitutto il 2a che indica l'algoritmo , quindi il "costo" utilizzato dall'algoritmo, quindi il 22-carattere salt (in testo normale), quindi l'hash attuale.

Il vantaggio di questo è che il controllo della password può essere eseguito utilizzando la stessa funzione utilizzata per il suo hashing: basta passare la stringa hash completa come salt e controllare se restituisce la stessa stringa. Un altro vantaggio, più rilevante, è il fatto che memorizzandolo in questo modo è possibile scrivere facilmente una funzione per gestire vari algoritmi di hash controllando il primo campo. Questo è rilevante quando devi gestire le password legacy che sono state sottoposte a hashing, ad es. usando MD5 o SHA-1.

    
risposta data 17.08.2013 - 13:09
fonte
3

Alcune funzioni di hashing della password codificano tradizionalmente il sale e l'output dell'hash come una singola stringa, quindi il sale è lì, ma non appare nel database come una colonna specifica. La maggior parte delle librerie bcrypt lo fanno. Potrebbe essere il caso del tuo sistema.

Inoltre, salt potrebbe essere implicito (ad esempio calcolato come concatenazione del nome utente e di un ID riga, o qualcosa del genere).

    
risposta data 17.08.2013 - 02:01
fonte
2

Il sale deve essere noto per verificare la password con hash. Non vi è alcun motivo per non archiviarlo con l'hash nel database poiché è perfettamente sicuro essere informazioni pubbliche. Lo scopo è solo quello di impedire l'uso di hash del precomputer per trovare rapidamente password non sicure.

    
risposta data 17.08.2013 - 01:10
fonte

Leggi altre domande sui tag