2009-03-05 15 views
75

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?Metodo preferito di memorizzazione delle password nel database

+1

ho la sensazione che questo può essere una vittima, ma quello che ho pensato potrebbe essere una vittima di esso si è rivelata per quanto riguarda gli accessi effettivi DB e non solo la memorizzazione di applicazione/sito login. – TheTXI

+1

Potresti chiarire la tua domanda per spiegare se stai utilizzando le funzioni "crittografia" o "hashing"? Penso che tu intenda il secondo, ma la differenza è molto significativa. – ine

risposta

80

devo conservare l'hash equivalente salata della password nel database e non la password stessa, poi sempre confrontare l'hash alla generato una delle ciò che l'utente passava.

È troppo pericoloso per memorizzare mai letterale dati della password ovunque Ciò rende impossibile il recupero, ma quando qualcuno dimentica o perde una password, è possibile eseguire alcuni controlli e creare una nuova password.

+0

@Quinton: Questo è praticamente quello che faccio. Con le librerie di crittografia .net, esso digiterà la password e quindi la passerò nel DB e la memorizzerò come un file binario. Posso solo confrontare le password mediante l'hashing di input dell'utente e confrontandolo con ciò che è memorizzato. – TheTXI

+0

Sembra che tu sia sulla strada giusta allora. –

+1

Raccomando jbcrypt se stai lavorando con java. Estremamente semplice da usare –

15

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 lo stiate facendo bene (dato che usate uno Salt).

+2

+1 per indirizzare la vera domanda qui. – erickson

46

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

+5

mod up, dovevo farlo, solo per lo scherzo di sale;) – Jakub

+0

ho sorriso anche a questo. –

8

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 campo binario non elaborato ha più senso, 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 si utilizza. 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 sul SO tale argomento:

+0

Se leggi la mia domanda un po 'più da vicino, vedresti che mi concentro più sull'archiviazione reale in termini di datatype e spazio assegnato per il campo. – TheTXI

+0

Ma +1 per fornire ulteriori informazioni ad altri che potrebbero venire in seguito. – TheTXI

+0

Proprio sopra. Sembra che io non sia l'unico a mancare;) – erickson

8
  1. negozio l'hash della password di-salato, come ad esempio bcrypt (nunciare + 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 "password dimenticata", assicurati che non invii la nuova password via email, ma invece dovrebbe inviare un collegamento 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, fissare il modulo di login (in genere con HTTPS) ei server stessi

Con queste misure, le password del vostro utente saranno abbastanza ben protetti contro:

  1. => non in linea attacchi del dizionario
  2. => attacchi del dizionario dal vivo
  3. => attacchi denial of service
  4. => ogni sorta di attacchi!
+0

Tutte queste misure possono essere implementate rapidamente e racchiudono un bel pugno per il minimo sforzo! +1 =) –

+0

Gli attacchi DOS sono legati alla sicurezza della password? – Arj

+1

@ a12jun: se hai un link "dimenticato la mia password" sul tuo sito web con un semplice "login", e un "per favore genera una nuova password e inviami via email", allora chiunque conosca il tuo login può costringerti a cambiare la tua password. Se lo automatizza per eseguire ogni 10 secondi, allora può negare l'accesso al tuo account. Se lo gestisce contro migliaia di utenti, probabilmente può far sì che molti di loro non apprezzino il tuo servizio. La linea guida n. 3 può proteggerti da questo, questo è quello che intendevo (non era molto chiaro, devo ammettere). Sicurezza = Riservatezza, integrità, *** *** ***. – MiniQuark

4

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

Sia consiglia gli algoritmi bcrypt. Le implementazioni gratuite possono essere trovate online per le lingue più diffuse.

+0

Ottimi collegamenti che vanno oltre i problemi di sicurezza superficiali. Per algoritmi volutamente lenti, sarebbe importante avere gli hash calcolati sul lato client in modo da non sovraccaricare il server (possibilmente già piuttosto occupato)? – cheduardo

+0

Non proprio. L'obiettivo è semplicemente quello di renderlo "leggermente" più lento. Solo per darti un'idea. Posso hash SHA1 circa 200K password al secondo su sistema quad core. Dubito che chiunque abbia bisogno di gestire accessi simultanei a 200K ogni secondo ... Quindi si usa una funzione come PBKDF2 o bcrypt per rallentarlo per dire solo 100 hash al secondo (aumenta la timeline della forza bruta di un fattore di 200). –

2

Se si utilizza ASP.Net è possibile 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 niente di troppo elegante, questo è ottimo per i siti web.

Se non si utilizza ASP.Net: ecco un buon collegamento a un paio di articoli da 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

4

Io uso l'hash SHA del nome utente, un GUID in la configurazione web 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 
); 
+0

ho usato per usare il nome utente come aggiunto sale. Ma poi non siamo stati in grado di rinominare un utente. Siamo passati a usare salt con l'id dell'utente, guid, sid o qualcos'altro chiave surrogata. –

+0

tru, buona chiamata. in questo modo non è necessario reimpostare la password quando si rinomina un utente – Shawn

3

È possibile utilizzare più hash nel 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.Io uso spesso voci di password come

{Hashid} $ {} sale $ {} password con hash

dove "Hashid" è solo un numero che uso internamente a riconoscere che, per esempio, sto usando SHA1 con un modello di hash specifico; "salt" è un sale casuale codificato in base64; e "password hash" è un hash codificato in base64. Se è necessario migrare gli hash, è possibile intercettare le persone con un vecchio formato di password e fargli cambiare la password al prossimo accesso.

Come altri hanno già detto, si vuole stare attenti con i propri hash poiché è facile fare qualcosa non è molto sicuro, ad esempio, H (salt, password) è molto più debole di H (password, salt), ma allo stesso tempo si desidera 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 di password con codifica 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 utilizzare 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.

+0

Non c'è nulla di così veloce e forte quando si tratta di hashing. Scusate.Se è veloce per te, è veloce per un attaccante di forza bruta. L'utilizzo di una funzione di derivazione della chiave è un metodo valido per il rafforzamento della password. –

2

Dato che la domanda riguarda il metodo di archiviazione &, la risolverò.

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 di hash. L'output di MD5 è sempre 16 byte, SHA1 è sempre 20 byte. SHA-256 & SHA-512 sono 32 & 64 byte rispettivamente. 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 si dispone di salatura per utente, sarà necessario anche 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 si desidera eseguire correttamente, non è necessario utilizzare 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 Net è RFC2892DeriveBytes http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx