Numero di round consigliati per bcrypt

71

Che cosa è oggi (luglio 2012) il numero consigliato di bcrypt round per l'hashing di una password per un sito web medio (che memorizza solo nome, indirizzo email e indirizzo di casa, ma nessuna carta di credito o informazioni mediche)?

In altre parole, qual è l'attuale capacità della comunità di cracking della password di bcrypt? Diverse librerie di bcrypt utilizzano 12 round (2 ^ 12 iterazioni) come impostazione predefinita. È il lavoratore consigliato? I 6 round non saranno abbastanza forti (il che è il limite per l'hashing di bcrypt lato client in Javascript, vedi anche Sfida di sfida: hashing della password sul lato client e verifica della password sul lato server )?

Ho letto la risposta link che offre una discussione approfondita su come bilanciare i vari fattori (anche se per PBKDF2-SHA256). Tuttavia, sto cercando un numero reale. Una regola empirica.

    
posta Jason Smith 14.07.2012 - 19:51
fonte

3 risposte

26

Penso che la risposta a tutte le tue domande sia già contenuta nella risposta di Thomas Pornin . Ci sei collegato, quindi presumibilmente lo sai, ma ti suggerisco di leggerlo di nuovo.

I principi di base sono: non scegliere un numero di round; invece, scegli la quantità di tempo che la verifica della password impiegherà sul tuo server, quindi calcola il numero di round in base a quello. Vuoi che la verifica duri tutto il tempo che puoi.

Per alcuni esempi di numeri concreti, vedere la risposta di Thomas Pornin. Suggerisce che un obiettivo ragionevole sarebbe per la verifica della password / hashing da 241 millisecondi per password. (Nota: Thomas ha inizialmente scritto "8 millisecondi", che è sbagliato - questa è la cifra per una pazienza di un giorno invece di un mese.) Ciò consente al server di verificare 4 password al secondo ( di più se puoi farlo in parallelo). Thomas stima che, se questo è il tuo obiettivo, circa 20.000 round sono nel giusto ballpark.

Tuttavia, il numero ottimale di colpi cambierà con il processore. Idealmente, si dovrebbe stabilire quanto tempo impiega il processore e scegliere il numero di conseguenza. Questo non richiede così tanto tempo; quindi, per ottenere i risultati migliori, basterà montare lo script e calcolare quanti cicli sono necessari per garantire che l'hashing della password impieghi circa 240 millisecondi sul server (o più lungo, se riesci a sopportarlo).

    
risposta data 16.07.2012 - 00:57
fonte
49

Quando BCrypt fu pubblicato per la prima volta, nel 1999, elencarono i fattori di costo di default della loro implementazione:

  • utente normale: 6
  • super utente: 8

Notano anche:

Of course, whatever cost people choose should be reevaluated from time to time

Un costo in bcrypt di 6 significa 64 round (2 6 = 64).

Se usiamo quel valore iniziale "utente normale" , vogliamo provare ad aggiustare il calcolo dell'inflazione della potenza ( supponendo che in media raddoppi ogni 18 mesi ).

R = R0 × 2(months/18)
R = 64 × 2(months/18)

Oggi (9 marzo 2015) è di 171 mesi dal 31/12/1999 (o usa 1/1/2000 per semplicità), il numero di giri dovrebbe essere raddoppiato un po 'più di 9 volte:

R = 64 × 2(171/18)
R = 64 × 29.5
R = 64 × 724.1
R = 46,341.0

Alla fine, vogliamo riconvertirlo in un fattore di costo

cost = ln(R) / ln(2)
cost = ln(46,341.0) / ln(2)
cost = 15.5

La praticità di un fattore di costo o 15 dipende dalla potenza di calcolo del tuo server. Ad esempio, il mio PC desktop è una CPU Intel Core i7-2700K a 3.50 GHz. Inizialmente ho eseguito il benchmarking di un'implementazione di BCrypt il 1/23/2014:

1/23/2014  Intel Core i7-2700K CPU @ 3.50 GHz

| Cost | Iterations        |    Duration |
|------|-------------------|-------------|
|  8   |    256 iterations |     38.2 ms | <-- minimum allowed by BCrypt
|  9   |    512 iterations |     74.8 ms |
| 10   |  1,024 iterations |    152.4 ms | <-- current default (BCRYPT_COST=10)
| 11   |  2,048 iterations |    296.6 ms |
| 12   |  4,096 iterations |    594.3 ms |
| 13   |  8,192 iterations |  1,169.5 ms |
| 14   | 16,384 iterations |  2,338.8 ms |
| 15   | 32,768 iterations |  4,656.0 ms |
| 16   | 65,536 iterations |  9,302.2 ms |

Ma era il 2014

Questi tempi sono stati originariamente calcolati all'inizio del 2014. Nei miei calcoli avrebbero dovuto essere utilizzati solo 156 mesi (anziché 171):

R = 64 × 2(156/18)
R = 64 × 28.66
R = 64 × 406.8
R = 26,035.2

cost = ln(R) / ln(2)
cost = ln(26,035.2) / ln(2)
cost = 14.7

Ma l'i7-2700K era già stato interrotto

L'i7-2700K era già stato interrotto (primo trimestre 2013) quando ho eseguito i miei benchmark. È stato rilasciato ed è stato all'avanguardia nel quarto trimestre del 2011. Se eseguo i numeri per il quarto trimestre del 2011:

R = 64 × 2(129/18)
R = 64 × 27.16
R = 64 × 143.7
R = 9,196.8

cost = ln(R) / ln(2)
cost = ln(9,196.8) / ln(2)
cost = 13.2

Un costo di 13 è, sul mio desktop, quasi 2 secondi in un secondo.

Per quanto tempo puoi sopportarlo?

Questo ti dà il sapore del tipo di ritardi che gli implementatori originali stavano prendendo in considerazione quando lo hanno scritto: ~ 0.5-1 secondo.

Ma, naturalmente, più a lungo puoi stare, meglio è. Ogni implementazione di BCrypt che ho visto utilizzava 10 come costo predefinito. E la mia implementazione l'ha usata. Credo che sia tempo per me di aumentare il costo predefinito a 12.

Proofing futuro

Potrei anche cambiare la funzione di hash:

hash = HashPassword("correct battery horse stapler");

vale a dire. quello in cui si fa affidamento sul costo predefinito, per utilizzare invece un costo scorrevole automaticamente. In questo modo il costo è auto-aumentante nel tempo. Modifica:

String HashPassword(String password)
{
   return BCrypt.HashPassword(password, BCRYPT_DEFAULT_COST);
}

in qualcosa di simile:

String HashPassword(String password)
{  
   /*
     Rather than using a fixed default cost, run a micro-benchmark
     to figure out how fast the CPU is.
     Use that to make sure that it takes **at least** 250ms to calculate
     the hash
   */
   Int32 costFactor = this.CalculateIdealCost();
   //Never use a cost lower than the default hard-coded cost
   if (costFactor < BCRYPT_DEFAULT_COST) 
      costFactor = BCRYPT_DEFAULT_COST;

   return BCrypt.HashPassword(password, costFactor);
}

Int32 CalculateIdealCost()
{
    //Benchmark using a cost of 5 (the second-lowest allowed)
    Int32 cost = 5;

    var sw = new Stopwatch();
    sw.Start();
    this.HashPassword("microbenchmark", cost);
    sw.Stop();

    Double durationMS = sw.Elapsed.TotalMilliseconds;

    //Increasing cost by 1 would double the run time.
    //Keep increasing cost until the estimated duration is over 250 ms
    while (durationMS < 250)
    {
       cost += 1;
       durationMS *= 2;
    }

    return cost;
}

Modifica 3/12/2015 : numeri di velocità aggiornati. Il compilatore Delphi XE6 a 32 bit (c.2013) genera un codice di un ordine di grandezza più veloce di quello di Delphi 5 (c.1999) per lo stesso processore. Il compilatore Delphi XE6 a 64 bit genera il codice più lento del 20% rispetto al compilatore a 32 bit.

    
risposta data 09.03.2015 - 16:31
fonte
3

Una più strong derivazione delle chiavi tramite sequenziali funzioni hard-memory è un ottimo documento sull'argomento dell'allungamento chiave. A pagina 14 confronta diversi algoritmi di hashing con quanti soldi avrà un costo per rompere l'hash, che è un modo utile di pensare a queste cose. (Nota a margine ChromeOS utilizza Scrypt se TPM non è disponibile.)

L'idea è che vuoi che questi hash della password siano ininterrotti il più a lungo possibile. Con la legge di Moore questo è un obiettivo in rapida crescita. Scrypt utilizza una quantità variabile di memoria e CPU, questa variabile potrebbe diventare più pesante in funzione del tempo. In questo ogni volta che il client esegue l'accesso, è possibile aggiornare l'hash della password per essere più sicuro. Nel caso di PBKDF2 questo potrebbe sembrare rounds=2^(current_year-2000) o qualcosa del genere.

È importante notare che non è possibile scaricare questa elaborazione sul client e aspettarsi che il protocollo sia sicuro. Tutti i protocolli di autenticazione hashing sul lato client che sono a conoscenza richiedono che il server esegua un calcolo identico per verificare le credenziali di autenticazione (NTLM, NTLMv2, SRP, WPA-PSK ...).

    
risposta data 14.07.2012 - 22:15
fonte

Leggi altre domande sui tag