2012-08-31 8 views
7

La prego di dirmi se la seguente è un buon modo per hash in modo sicuro una password da memorizzare in un database:È un modo sicuro per cancellare una password?

public string CreateStrongHash(string textToHash) { 

     byte[] salt =System.Text.Encoding.ASCII.GetBytes("TeStSaLt"); 

     Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(textToHash, salt, 1000); 
     var encryptor = SHA512.Create(); 
     var hash = encryptor.ComputeHash(k1.GetBytes(16)); 

     StringBuilder sb = new StringBuilder(); 
     for (int i = 0; i < hash.Length; i++) { 
      sb.Append(hash[i].ToString("x2")); 
     } 

     return sb.ToString(); 

    } 

Molte grazie in anticipo.

+4

Idealmente penso che dovresti avere un sale diverso per utente e archiviarlo anche nel database. – Bridge

+1

Scusate se sono un po 'denso, ma se qualcuno accede al database, la memorizzazione del sale non rende più facile a qualcuno di crackare la crittografia? – ScubaSteve2012

+0

@ ScubaSteve2012 Il sale previene gli attacchi di hash precalcolati ("Tabelle arcobaleno"). Poiché le password sono salate, la tua tabella arcobaleno sarebbe inutile per aiutare a capire le password originali. Dovresti creare una nuova tabella arcobaleno usando questo hash, che è praticamente un attacco a forza bruta. – Oleksi

risposta

7

Si utilizza PBKDF2-SHA1, che è decente, ma non eccezionale. Bcrypt è un po 'meglio, e lo scrypt è ancora più forte. Ma poiché .net include già un'implementazione integrata in PBKDF2, questa è una scelta accettabile.

Il tuo più grande errore è che non hai ottenuto il punto di un sale. Un sale dovrebbe essere unico per ogni utente. È prassi normale creare semplicemente un valore casuale di almeno 64 bit. Memorizzalo insieme all'hash nel database.

Se si desidera, è possibile dividere il sale in due parti. Uno memorizzato nel database accanto all'utente, che è diverso per ciascuno, e una parte condivisa memorizzata altrove. Questo guadagna i vantaggi di entrambi.

Si consiglia inoltre di utilizzare un fattore di lavoro superiore a 1000. Capire quali sono le prestazioni accettabili e regolare di conseguenza. Non andrei al di sotto del 10000, e in alcune situazioni (crittografia del disco) un milione è accettabile.

+0

Grazie per il vostro aiuto. – ScubaSteve2012

+0

Se il valore di sale è memorizzato, come tale, nel database, è di pochissimo aiuto per evitare di trovare una collisione. La sua utilità principale in quel caso è impedire a un utente malintenzionato di scoprire tramite ispezione che due utenti hanno la stessa password. Sarebbe preferibile utilizzare dati che non sono specificatamente etichettati come "sale", o anche meglio, che non sono contenuti nello stesso archivio dati; l'utente malintenzionato deve quindi non solo compromettere il database contenente gli hash, ma il codebase e/o un archivio dati aggiuntivo, al fine di determinare cosa utilizzare come sale e come. – KeithS

+0

@KeithS Non ho mai menzionato la parola collisione, perché le collisioni sono irrilevanti qui. Il punto principale di un sale è essere unico, e quindi prevenire attacchi multi-target. Aggiungere un segreto archiviato in posizioni separate è un bel extra, ma non il punto principale di un sale. – CodesInChaos

5

Può essere migliorato. Per prima cosa, dovresti usare invece bcrypt. Gli hash tradizionali come SHA-512 possono essere suddivisi abbastanza facilmente con le GPU ora a un giorno. Il problema è che questi hash sono progettati per la velocità, e questo è l'opposto di ciò che si desidera in un hash della password. Bcrypt è un esempio di un algoritmo di hash adattivo. Può essere configurato in modo da richiedere un tempo "lungo" (ma comunque non causerà problemi di prestazioni nel sistema) per rendere difficile la definizione di forza bruta.

Si desidera anche rendere i sali univoci per ciascun utente.

Per ulteriori informazioni sulle modalità di hash password sicure, vedere this question.

+3

Sta usando PBKDF2, che è un po 'peggio di bcrypt, ma comunque una delle funzioni raccomandate. – CodesInChaos

+0

SHA-512 è letteralmente "abbastanza buono per il lavoro di governo"; è considerato crittograficamente forte e non esiste una "scorciatoia" nota che riduca la complessità di trovare la soluzione. Il fatto che qualsiasi problema possa essere risolto "più velocemente" lanciando abbastanza hardware è irrilevante; dovresti provare 5.2 × 10^72 valori prima di avere una probabilità 1 su un miliardo * di scontrarsi con qualsiasi hash generato in precedenza. – KeithS

+1

@KeithS Plain SHA-512 non è considerato sufficiente per applicazioni come l'hashing della password, perché è troppo veloce. Con l'hashing delle password si utilizzano funzioni volutamente costose per compensare la mancanza di entropia in una password. | PBKFDF2 con SHA-512 d'altra parte è decente. – CodesInChaos

Problemi correlati