it-swarm.it

Numero consigliato di round per bcrypt

Qual è al giorno d'oggi (luglio 2012) il numero raccomandato di round criptati per l'hashing di una password per un sito Web medio (che memorizza solo nome, indirizzo e-mail e indirizzo di casa, ma nessuna carta di credito o informazioni mediche)?

In altre parole, qual è l'attuale capacità della comunità di cracking delle password di bcrypt? Diverse librerie bcrypt usano 12 round (2 ^ 12 iterazioni) come impostazione predefinita. È il fattore di lavoro raccomandato? 6 round non sarebbero abbastanza forti (che sembra essere il limite dell'hash bcrypt lato client in Javascript, vedi anche Sfida impegnativa: hashing password lato client e verifica password lato server )?

Ho letto la risposta https://security.stackexchange.com/a/3993/11197 che fornisce una discussione approfondita su come bilanciare i vari fattori (anche se per PBKDF2-SHA256). Tuttavia, sto cercando un numero reale. Una regola empirica.

94
Jason Smith

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

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

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

Tuttavia, il numero ottimale di round cambierà con il tuo processore. Idealmente, dovresti valutare quanto tempo impiega il tuo processore e scegliere il numero di conseguenza. Non ci vuole molto tempo; quindi per ottenere i migliori risultati, basta montare lo script ed elaborare quanti round sono necessari per garantire che l'hash della password impieghi circa 240 millisecondi sul server (o più a lungo, se è possibile sopportarlo).

41
D.W.

Quando BCrypt è stato pubblicato per la prima volta, nel 1999, hanno elencato i fattori di costo predefiniti della loro implementazione:

  • utente normale: 6
  • superutente: 8

Notano anche:

Ovviamente, qualunque costo scelga la gente dovrebbe essere rivalutato di volta in volta

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

Se utilizziamo quel valore iniziale "utente normale", vogliamo provare ad adeguarci per l'inflazione della potenza di calcolo ( supponendo che in media raddoppi ogni 18 mesi ).

R = R × 2(Mesi/18)
R = 64 × 2(Mesi/18)

Oggi (9 marzo 2015) sono 171 mesi dal 31/12/1999 (o usare 1/1/2000 per semplicità), il numero di round dovrebbe essere raddoppiato poco 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

costo = ln (R)/ln (2)
costo = ln (46.341,0)/ln (2)
Costo = 15,5

La praticità di un fattore di costo di 15 dipende dalla potenza di calcolo del server. Ad esempio, il mio PC desktop è una CPU Intel Core i7-2700K a 3,50 GHz. Inizialmente ho confrontato un'implementazione di BCrypt il 23/01/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 quello era il 2014

Tali tempistiche sono state originariamente calcolate all'inizio del 2014. Nel mio calcolo avrebbero dovuto essere stati utilizzati solo 156 mesi (anziché 171):

R = 64 × 2(156/18)
R = 64 × 28.66
R = 64 × 406,8
R = 26.035,2

costo = ln (R)/ln (2)
costo = ln (26.035,2)/ln (2)
costo = 14.7

Ma l'i7-2700K era già fuori produzione

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

R = 64 × 2(129/18)
R = 64 × 27.16
R = 64 × 143,7
R = 9.196,8

costo = ln (R)/ln (2)
costo = ln (9.196,8)/ln (2)
costo = 13.2

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

Quanto a lungo lo sopporti?

Questo ti dà un'idea del tipo di ritardi che gli implementatori originali stavano considerando quando lo hanno scritto: ~ 0,5-1 secondi.

Ma, naturalmente, più a lungo riesci a stare in piedi, meglio è. Ogni implementazione BCrypt che ho visto usato 10 come costo predefinito. E la mia implementazione l'ha usato. Ritengo sia giunto il momento di aumentare il costo predefinito a 12.

Prove future

Potrei anche cambiare la funzione hash:

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

cioè quello in cui si fa affidamento sul costo predefinito, per utilizzare invece un costo a scorrimento automatico. In questo modo il costo si auto-aumenta nel tempo. Mutevole:

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

a qualcosa come:

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 Delphi 5 (c.1999) fatto per lo stesso processore. Il compilatore Delphi XE6 a 64 bit genera un codice più lento del 20% rispetto al compilatore a 32 bit.

61
Ian Boyd

Più forte derivazione dei tasti tramite funzioni sequenziali di memoria dura è un ottimo documento sull'argomento dello stiramento dei tasti. A pagina 14 confronta vari algoritmi di hashing con quanti soldi costerà per rompere l'hash, che è un modo utile di pensare a queste cose. (A parte, ChromeOS utilizza Scrypt se TPM non è disponibile.)

L'idea è che si desidera che questi hash password non vengano interrotti il ​​più a lungo possibile. Con la legge di Moore, questo è un bersaglio esponenzialmente rapido. 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 accede è possibile aggiornare l'hash della password per renderlo più sicuro. Nel caso di PBKDF2 questo potrebbe apparire come 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 hash lato client che conosco richiedono che il server esegua un calcolo identico per verificare le credenziali di autenticazione (NTLM, NTLMv2, SRP, WPA-PSK ...).

3
rook