Domanda

Qual è il tuo metodo / tipo di dati preferito per archiviare le password in un database (preferibilmente SQL Server 2005). Il modo in cui l'ho fatto in molte delle nostre applicazioni è innanzitutto quello di utilizzare le librerie di crittografia .NET e quindi di memorizzarle nel database come binario (16). È questo il metodo preferito o dovrei utilizzare un tipo di dati diverso o allocare più spazio di 16?

È stato utile?

Soluzione

Archivo l'equivalente hash salato della password nel database e mai la password stessa, quindi confronto sempre l'hash con quello generato di ciò che l'utente ha passato.

È troppo pericoloso archiviare i dati letterali 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.

Altri suggerimenti

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 per il fatto che è memorizzato come stringa. I Base64 codifica il valore binario crittografato. La quantità di spazio da allocare dipende dall'algoritmo di crittografia / intensità della crittografia.

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

  1. archivia l'hash della password salata, come bcrypt (nounce + pwd). Potresti preferire bcrypt su SHA1 o MD5 perché può essere ottimizzato per un uso intensivo della CPU, rendendo quindi un attacco di forza bruta molto più lungo.
  2. aggiungi un captcha al modulo di accesso dopo alcuni errori di accesso (per evitare attacchi di forza bruta)
  3. se la tua applicazione ha un " ho dimenticato la mia password " link, assicurati che non invii la nuova password via e-mail, ma dovrebbe invece inviare un link a una pagina (protetta) che consenta all'utente di definire una nuova password (possibilmente solo dopo la conferma di alcune informazioni personali, come la nascita dell'utente data, 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 dei tuoi utenti saranno abbastanza ben protette da:

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

Poiché il risultato di una funzione 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), la sua memorizzazione come campo binario non elaborato rende il più sensato, in quanto è la rappresentazione più compatta e non richiede ulteriori passaggi 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 utilizzare una codifica da binario a testo come Base-64 o Base-85 e memorizzare il testo risultante in un campo di caratteri.

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


Per quanto riguarda il "migliore" modo di eseguire l'hash, ho provato a fornire molte risposte ad altre domande SO su questo argomento:

Uso lo hash sha del nome utente, una guida nella configurazione web e la password, memorizzata come varchar (40). Se vogliono forzare la forza / il dizionario, dovranno hackerare il web server anche per il guid. Il nome utente si interrompe creando una tabella arcobaleno in tutto il database se trovano la password. Se un utente desidera modificare il proprio nome utente, ho semplicemente reimpostato la password contemporaneamente.

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

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

vedi:

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 bcrypt. Le implementazioni gratuite sono disponibili online per le lingue più popolari.

Puoi usare più hash nel tuo database, richiede solo un po 'di sforzo in più. Ne vale la pena, tuttavia, se pensi che ci sia la possibilità più remota di dover supportare formati aggiuntivi in ??futuro. Userò spesso voci di password come

{hashId} $ {salt} $ {password hash}

dove " hashId " è solo un numero che uso internamente per riconoscere che, ad esempio, sto usando SHA1 con un modello di hash specifico; & Quot; sale " è un sale casuale codificato in base64; e " password con hash " è un hash con codifica base64. Se devi migrare gli hash, puoi intercettare le persone con un vecchio formato di password e farli cambiare la password al successivo accesso.

Come altri hanno già detto, vuoi stare attento con i tuoi hash poiché è facile fare qualcosa che non è veramente 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 di password con codifica base64 è modesto rispetto ai 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 qualche byte per record? : -)

Modificato per aggiungere un altro commento: se suggerissi di usare deliberatamente un algoritmo che bruciava anche un 1/10 di secondo di hashing di ogni password, sarei fortunato ad essere deriso dall'ufficio del mio capo. (Non così fortunato? Scriverebbe qualcosa per discutere alla mia prossima recensione annuale.) Bruciare quel tempo non è un problema quando hai dozzine, o addirittura centinaia, di utenti. Se stai spingendo 100k utenti di solito avrai più persone che accedono contemporaneamente. Hai bisogno di qualcosa di veloce e forte, non lento e forte. Il " ma per quanto riguarda le informazioni sulla carta di credito? & Quot; nella migliore delle ipotesi è insignificante poiché le informazioni memorizzate sulla carta di credito non dovrebbero trovarsi in nessun posto vicino al normale database e sarebbero comunque criptate dall'applicazione, non dai singoli utenti.

Se si lavora con 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 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

Poiché la tua domanda riguarda il metodo di archiviazione e amp; dimensione che affronterò.

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

La dimensione dipende dall'algoritmo hash. L'output di MD5 è sempre di 16 byte, SHA1 è sempre di 20 byte. SHA-256 e amp; SHA-512 sono 32 e amp; 64 byte rispettivamente. Se stai utilizzando la codifica del testo, avrai bisogno di un po 'più di memoria a seconda del metodo di codifica. Tendo a utilizzare Base64 perché l'archiviazione è relativamente economica. Base64 richiederà un campo più grande di circa il 33%.

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

Infine, se vuoi farlo nel modo giusto, non dovresti usare un singolo hash ma una funzione di derivazione chiave come RBKDF2. Gli hash SHA1 e MD5 sono incredibilmente veloci. Anche una singola applicazione con thread può eseguire il hash da circa 30K a 50K password al secondo, ovvero fino a 200K password al secondo su macchine quad core. Le GPU possono hash da 100 a 1000 volte il numero di password al secondo. Con velocità come quella degli attacchi di forza bruta diventa un metodo di intrusione accettabile. RBKDF2 ti consente di specificare il numero di iterazioni per mettere a punto come "rallentare" il tuo hashing è. Il punto non è di mettere in ginocchio il sistema ma di scegliere un numero di iterazioni in modo da limitare il limite superiore della velocità effettiva dell'hash (ad esempio 500 hash al secondo). Un metodo a prova di futuro sarebbe quello di includere il numero di iterazioni nel campo password (iterazioni + salt + hash). Ciò consentirebbe alle crescenti iterazioni in futuro di stare al 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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top