Metodo preferito di memorizzazione delle password nel database

Qual è il metodo / tipo di dati preferito per la memorizzazione delle password in un database (preferibilmente SQL Server 2005). Il modo in cui lo sto facendo in molte delle nostre applicazioni è di usare prima le librerie di crittografia .NET e poi memorizzarle nel database come binari (16). È questo il metodo preferito o dovrei utilizzare un diverso tipo di dati o allocare più spazio di 16?

Memorizzo l’hash salato equivalente della password nel database e mai la stessa password, quindi confronta sempre l’hash con quello generato da ciò che l’utente ha passato.

È troppo pericoloso archiviare i dati letterali della password ovunque. Ciò rende imansible il recupero, ma quando qualcuno dimentica o perde una password, è ansible eseguire alcuni controlli e creare una nuova password.

IL metodo preferito: non memorizzare mai le password nel tuo DB. Solo hash di ciò. Aggiungi sale a piacere.

Faccio la stessa cosa che hai descritto, tranne che è memorizzato come una stringa. I Base64 codifica il valore binario crittografato. La quantità di spazio da allocare dipende dall’algoritmo di cifratura / forza di cifratura.

Penso che tu stia facendo bene (dato che usi un sale ).

Poiché il risultato di una funzione di hash è una serie di byte nell’intervallo da 0 a 255 (o da -128 a 127, a seconda della firma del tipo di dati a 8 bit), memorizzarlo come un campo binario non elaborato è più sensato , in quanto è la rappresentazione più compatta e non richiede passaggi aggiuntivi di codifica e decodifica.

Alcuni database o driver non hanno un grande supporto per i tipi di dati binari, o talvolta gli sviluppatori non hanno abbastanza familiarità con loro per sentirsi a proprio agio. In tal caso, è accettabile l’utilizzo di una codifica da binario a testo come Base-64 o Base-85 e la memorizzazione del testo risultante in un campo di caratteri.

La dimensione del campo necessario è determinata dalla funzione di hash che usi. MD5 emette sempre 16 byte, SHA-1 emette sempre 20 byte. Una volta che selezioni una funzione di hash, di solito sei bloccato con esso, poiché la modifica richiede il ripristino di tutte le password esistenti. Quindi, usare un campo di dimensioni variabili non ti compra nulla.


Per quanto riguarda il modo “migliore” per eseguire l’hashing, ho cercato di fornire molte risposte ad altre domande SO su quell’argomento:

  • Crittografia delle password
  • Crittografia delle password
  • Crittografia delle password in .NET
  • sale
  • Sale: segreto o pubblico?
  • Hash iterations
  1. memorizzare l’hash della password salata, come bcrypt (nounce + pwd). Potresti preferire bcrypt su SHA1 o MD5 perché può essere regolato in modo da richiedere un uso intensivo della CPU, rendendo così un attacco di forza bruta più a lungo.
  2. aggiungi un captcha al modulo di accesso dopo alcuni errori di accesso (per evitare attacchi brute-force)
  3. se la tua applicazione ha un link “Ho dimenticato la mia password”, assicurati che non invii la nuova password via email, ma invece dovrebbe inviare un link a una pagina (protetta) che consente all’utente di definire una nuova password (probabilmente solo dopo la conferma) di alcune informazioni personali, come ad esempio la data di nascita dell’utente, ad esempio). Inoltre, se l’applicazione consente all’utente di definire una nuova password, assicurarsi di richiedere all’utente di confermare la password corrente.
  4. e ovviamente, proteggere il modulo di accesso (in genere con HTTPS) e i server stessi

Con queste misure, le password dell’utente saranno abbastanza ben protette da:

  1. => attacchi dizionario offline
  2. => attacchi di dizionario dal vivo
  3. => attacchi denial of service
  4. => tutti i tipi di attacchi!

Io uso l’hash sha del nome utente, un guid nel web config e la password, memorizzata come varchar (40). Se vogliono il dominio / forza bruta avranno bisogno di hackerare il web server anche per guid. Il nome utente interrompe la creazione di una tabella arcobaleno nell’intero database se trova la password. Se un utente vuole cambiare il suo nome utente, ho appena resettato la password allo stesso tempo.

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile( username.ToLower().Trim(), ConfigurationManager.AppSettings("salt"), password ); 

Un semplice hash della password, o anche (salt + password) non è generalmente adeguato.

vedere:

http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/

e

http://gom-jabbar.org/articles/2008/12/03/why-you-should-use-bcrypt-to-store-your-passwords

Entrambi raccomandano gli algoritmi di bcrypt. Le implementazioni gratuite possono essere trovate online per le lingue più diffuse.

Puoi usare più hash nel tuo database, richiede solo un po ‘di sforzo in più. Ne vale la pena, anche se pensi che ci sia la minima possibilità che tu abbia bisogno di supportare formati aggiuntivi in ​​futuro. Userò spesso voci di password come

{hashId} $ {salt} $ {hashed password}

dove “hashId” è solo un numero che uso internamente per riconoscere che, ad esempio, sto usando SHA1 con uno specifico pattern di hash; “salt” è un sale casuale codificato in base64; e “password hash” è un hash codificato in base64. Se hai bisogno di migrare gli hash, puoi intercettare le persone con un vecchio formato di password e fargli cambiare la loro password al prossimo accesso.

Come altri hanno già detto, vuoi stare attento con i tuoi hash dato che è facile fare qualcosa che non è sicuro, ad esempio, H (salt, password) è molto più debole di H (password, salt), ma allo stesso tempo vuoi bilanciare lo sforzo messo in questo con il valore del contenuto del sito. Userò spesso H (H (password, salt), password).

Infine, il costo dell’utilizzo delle password codificate in base64 è modesto se confrontato con i vantaggi di poter utilizzare vari strumenti che prevedono dati di testo. Sì, dovrebbero essere più flessibili, ma sei pronto a dire al tuo capo che non può usare il suo strumento di terze parti preferito perché vuoi salvare pochi byte per record? 🙂

Modificato per aggiungere un altro commento: se ho suggerito deliberatamente di usare un algoritmo che ha bruciato anche un decimo di secondo di hashing di ciascuna password, sarei fortunato ad essere semplicemente deriso dall’ufficio del mio capo. (Non è così fortunato? Avrebbe buttato giù qualcosa da discutere alla mia prossima revisione annuale.) Bruciare quel tempo non è un problema quando si hanno decine o addirittura centinaia di utenti. Se stai spingendo 100k utenti, in genere avrai più persone che accedono allo stesso tempo. Hai bisogno di qualcosa di veloce e forte, non lento e forte. Il “ma per quanto riguarda le informazioni sulla carta di credito?” è alquanto disonesto dal momento che le informazioni memorizzate sulla carta di credito non dovrebbero essere vicine al tuo normale database e sarebbero comunque crittografate dall’applicazione, non da singoli utenti.

Se si sta lavorando con ASP.Net è ansible utilizzare l’API di appartenenza integrata.

Supporta molti tipi di opzioni di archiviazione, incluso; hash unidirezionale, crittografia bidirezionale, md5 + salt. http://www.asp.net/learn/security per maggiori informazioni.

Se non hai bisogno di qualcosa di troppo elegante, questo è ottimo per i siti web.

Se non stai usando ASP.Net ecco un buon link ad alcuni articoli di 4guys e codeproject

http://aspnet.4guysfromrolla.com/articles/081705-1.aspx http://aspnet.4guysfromrolla.com/articles/103002-1.aspx http://www.codeproject.com/KB/security/SimpleEncryption. aspx

Dal momento che la tua domanda riguarda il metodo e le dimensioni dello storage, lo affronterò.

Il tipo di archiviazione può essere di tipo binario o di testo (base64 è il più comune). Il binario è più piccolo ma trovo più facile lavorare con il testo. Se si sta eseguendo la salatura per utente (differenza di sale per password), è più semplice memorizzare salt + hash come una singola stringa combinata.

La dimensione dipende dall’algoritmo hash. L’output di MD5 è sempre 16 byte, SHA1 è sempre 20 byte. SHA-256 e SHA-512 sono rispettivamente 32 e 64 byte. Se si utilizza la codifica del testo, sarà necessario un po ‘più di spazio in base al metodo di codifica. Tendo ad usare Base64 perché lo storage è relativamente economico. Base64 richiederà circa il 33% di spazio in più.

Se hai una salatura per utente, avrai anche bisogno di spazio per l’hash. Mettere tutto insieme 64bit sale + SHA1 hash (160 bit) codificato base64 richiede 40 caratteri quindi lo memorizzo come char (40).

Infine, se vuoi farlo bene, non dovresti usare un singolo hash ma una funzione di derivazione della chiave come RBKDF2. Gli hash SHA1 e MD5 sono incredibilmente veloci. Anche una singola applicazione con thread può eseguire hash da 30 a 50 KB di password al secondo, fino a 200 KB di password al secondo su computer quad core. Le GPU possono eseguire hash da 100 a 1000 volte quante più password al secondo. Con velocità simili all’attacco di forza bruta diventa un metodo di intrusione accettabile. RBKDF2 consente di specificare il numero di iterazioni per ottimizzare la “lentezza” dell’hashing. Il punto non è quello di mettere il sistema in ginocchio, ma di scegliere un numero di iterazioni in modo da limitare il limite superiore sulla velocità hash (diciamo 500 hash al secondo). Un metodo a prova di futuro sarebbe quello di includere il numero di iterazioni nel campo della password (iterazioni + sale + hash). Ciò consentirebbe di aumentare le iterazioni in futuro per tenere il passo con processori più potenti. Per essere ancora più flessibile utilizzare varchar per consentire hash potenzialmente più grandi / alternativi in ​​futuro.

L’implementazione di .Net è RFC2892DeriveBytes http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx