2009-08-31 10 views
17

sto lavorando su una funzionalità di crittografia basata su classi ereditate da SymmetricAlgorithm quali TripleDES, DES, eccPasswordDeriveBytes vs Rfc2898DeriveBytes, obsoleto, ma il modo più veloce

Fondamentalmente Ci sono due opzioni per generare chiave coerente e IV la mia classe algoritmica, PasswordDeriveBytes e Rfc2898DeriveBytes, entrambi ereditano dalla classe astratta DeriveBytes.

Il metodo PasswordDeriveBytes.GetBytes() è contrassegnato come obsoleto in .NET framework mentre è consigliato Rfc2898DeriveBytes.GetBytes(), poiché corrisponde allo standard PBKDF2. Tuttavia, in base ai miei test, la chiamata allo stesso metodo GetBytes() nella classe Rfc2898DeriveBytes è quasi 15 volte più lenta di quella nella classe PasswordDeriveBytes, che comporta un utilizzo imprevisto della CPU (sempre superiore al 50%).

Here're alcuni dati di test:

  • Iterations: 100
  • Tipo Algoritmo: DES
  • Testo originale: "Sono una chiave di prova, mi crittografare favore"
  • Tempo:
    • PasswordDeriveBytes: 99ms
    • Rfc2898DeriveBytes: 1,373ms

Sulla base del test, i risultati negativi Rfc2898DeriveBytes non è accettabile in ambiente di produzione.

Qualcuno ha notato questo problema prima? Qualche soluzione posso ancora usare uno standard senza colpire le prestazioni? Qualche rischio di utilizzare un metodo obsoleto (potrebbe essere rimosso nella versione futura)?

Grazie ragazzi!

Edit:

Probabilmente ho trovato dove il problema è ... Il numero di conteggio di default iterazione per PasswordDeriveBytes è 100, mentre per Rfc2898DeriveBytes è 1000. Dopo li ho cambiato allo stesso numero nel 1000, l'esecuzione Rfc2898DeriveBytes è solo doppio tempo.

+0

Con quale frequenza si stanno derivando le chiavi in ​​un ambiente di produzione? E, per quanto riguarda i tuoi dati di tempistica, quando hai detto "100 iterazioni" - sono le iterazioni sul tasto onee, o hai generato 100 chiavi. Qualsiasi dato perf basato su 100 prove è sospetto, ma penso che tu abbia effettivamente provato UNA prova. Come in tutti i casi di analisi perf, non è appropriato trarre conclusioni sulle prestazioni del server in base al tempo di risposta di una singola prova. – Cheeso

+0

@Cheeso Il test era solo un test unitario delle prestazioni per queste due classi e non è stato eseguito in un'app reale. Le "100 iterazioni" che ho citato sono state un po 'confuse, questo significa solo che ho eseguito ognuna di esse 100 volte. Non è un vero test di perf, ma solo un confronto. – tshao

+5

Penso che potresti aver perso il punto in cui 'Rfc2898DeriveBytes' è fondamentalmente _designed_ essere lento cosicché i controlli hash delle password (eseguiti per log-in e quindi abbastanza rari) non si accorgano del colpo sulle prestazioni mentre gli attacchi brute force fanno. Se hai bisogno di generare un sacco di hash 'Rfc2898DeriveBytes' non fa per te, ma se hai bisogno di sicurezza dagli attacchi brute force lo è. – Keith

risposta

25

Essi non sono la stessa cosa.

Rfc2898DeriveBytes è un'implementazione di PBKDF2. PasswordDeriveBytes è un'implementazione di PBKDF1. PBKDF2 genera un output diverso, utilizzando un metodo diverso e un numero molto maggiore di round rispetto a PBKDF1.

Le funzioni di hashing della password, come ad esempio queste, utilizzate per la derivazione della chiave devono essere lente. Questo è il punto: li rende molto più difficili da decifrare.

Le due funzioni non sono compatibili e PasswordDeriveBytes non è altrettanto sicuro.

+0

Grazie BlackAura. Posso capire che l'implementazione di PBKDF2 dovrebbe essere lenta, ma non esiste alcuna procedura migliore per utilizzare la classe Rfc2989DeriveBytes, ad esempio come memorizzare/riutilizzare la stessa chiave/IV? Eseguire un metodo più volte lento come quello nell'ambiente di produzione non è accettabile. : P – tshao

+4

In genere, si desidera utilizzare solo queste funzioni per generare una chiave da una password. Solitamente per qualcosa come un archivio protetto da password o simile. Per encrpyt un archivio, si genera un IV casuale e si genera una chiave dalla password e IV. Si salva la IV (ma mai la chiave). È quindi possibile riutilizzare la chiave per ogni file nell'archivio, purché ogni file sia crittografato con un IV diverso (anch'esso archiviato nell'archivio). L'unico altro uso per queste funzioni è l'hashing della password. Lo faresti una volta, quando un utente effettua il login. Per qualsiasi altro uso, c'è probabilmente un modo migliore. – BlackAura

9

Penso che manchi il punto di derivebytes. Dovrebbe essere lento. Utilizza intenzionalmente un algoritmo lento che non può essere accelerato da un trucco intelligente.Il tipico parametro "numero di iterazioni" dovrebbe essere compreso nell'intervallo 2^16-2^20 e introdurre un ritardo di 0,1-0,5 secondi tra l'immissione della password dell'utente e la generazione della chiave. L'intenzione è di difendersi da password deboli selezionate da "utenti ignoranti pigri" e rallentare la ricerca della forza bruta.