Optimaler bcrypt-Arbeitsfaktor

80

Was wäre ein idealer bcrypt-Arbeitsfaktor für das Passwort-Hashing?

Wenn ich den Faktor 10 verwende, dauert es ungefähr 0,1 Sekunden, um ein Passwort auf meinem Laptop zu hashen. Wenn wir am Ende eine sehr geschäftige Site haben, wird dies zu einer Menge Arbeit, bei der nur die Passwörter der Leute überprüft werden.

Vielleicht wäre es besser, einen Arbeitsfaktor von 7 zu verwenden, um die gesamte Passwort-Hash-Arbeit auf etwa 0,01 Sekunden pro Laptop-Login zu reduzieren?

Wie entscheiden Sie den Kompromiss zwischen Brute-Force-Sicherheit und Betriebskosten?

Chris
quelle
7
Die Kosten verhindern Offline-Angriffe. Wenn Sie "online" sind, können Sie eine minimale Verzögerung zwischen den Versuchen (z. B. 5 Sekunden) verwenden, um einen Denial-of-Service-Angriff zu verhindern.
Ian Boyd
3
Duplikat auf InformationSecurity: Empfohlene
Anzahl
1
Für alle Interessierten habe ich gerade ein kleines Java CLI-Tool geschrieben, um die Leistung von bcrypt auf Servern zu testen (was offensichtlich wichtig ist, um Sicherheit, Serverlast und Antwortzeiten in Einklang zu bringen
Blacklight

Antworten:

103

Denken Sie daran, dass der Wert im Passwort gespeichert ist : $2a$(2 chars work)$(22 chars salt)(31 chars hash). Es ist kein fester Wert.

Wenn Sie feststellen, dass die Last zu hoch ist, machen Sie es einfach so, dass Sie beim nächsten Anmelden auf etwas kryptisieren, das schneller berechnet werden kann. Wenn die Last kein Problem darstellt, können Sie im Laufe der Zeit die Stärke ihres Hashs verbessern, wenn sie sich anmelden.

Der Trick besteht darin, dass es zusammen mit Moores Gesetz ungefähr genauso lange dauert wie in der Zukunft. Die Nummer ist log2. Fügen Sie also jedes Mal, wenn sich die Geschwindigkeit von Computern verdoppelt, 1 zur Standardnummer hinzu.

Entscheiden Sie, wie lange es dauern soll, bis das Kennwort eines Benutzers brutal erzwungen wird. Bei einigen gängigen Wörterbuchwörtern beispielsweise hat Ihre Kontoerstellung sie wahrscheinlich bereits gewarnt, dass ihr Kennwort schwach war. Wenn es sich beispielsweise um eines von 1000 gebräuchlichen Wörtern handelt und ein Angreifer 0,1 Sekunden benötigt, um jedes zu testen, kauft er 100 Sekunden (einige Wörter sind häufiger ...). Wenn ein Benutzer "allgemeines Wörterbuchwort" + 2 Zahlen gewählt hat, sind das mehr als zwei Stunden. Wenn Ihre Kennwortdatenbank kompromittiert ist und der Angreifer nur wenige hundert Kennwörter pro Tag erhalten kann, haben Sie die meisten Benutzer Stunden oder Tage gekauft, um ihre Kennwörter sicher zu ändern. Es geht darum, ihnen Zeit zu verschaffen.

http://www.postgresql.org/docs/8.3/static/pgcrypto.html hat einige Zeiten zum Knacken von Passwörtern, die Sie berücksichtigen sollten. Natürlich sind die Passwörter, die sie dort auflisten, zufällige Buchstaben. Wörterbuchwörter ... Praktisch kann man den Kerl mit dem Passwort 12345 nicht retten.

Zer
quelle
8
Dies ist wirklich eine ausgezeichnete Antwort. Ich hatte nicht einmal über die Idee der erneuten Verschlüsselung beim Anmelden nachgedacht. Ich danke dir sehr!
Chris
1
Wie würde die Verschlüsselung funktionieren? Sie müssten die alten bcrypt-Arbeitskosten irgendwo speichern, damit Sie sie anmelden können. Nach der Überprüfung des Kennworts würden Sie den Hash und die Kosten in der Datenbank aktualisieren.
Jerry Saravia
6
@JerrySaravia Das Schöne an bcrypt ist, dass die Kosten im Hash selbst gespeichert sind - Sie müssen also nichts extra speichern . Authentifizieren Sie sich einfach mit dem aktuellen Hash und generieren Sie den Hash sofort mit anderen Kosten neu. Einfach!
Mark Locker
@ MarkLocker, danke Mark! Es ist eine B-Krypta! Aber im Ernst, das macht die Sache viel einfacher und ist eine wunderbare Sache.
Jerry Saravia
Okay, da ich es nicht bearbeiten darf, weil es ein "falscher Versuch zu antworten" ist (habt ihr überhaupt meine Änderungen gelesen?), Erlaube mir stattdessen, die Informationen zu kommentieren. Beispielwert : $2y$08$fJS4yx0i8kiOzIBIamZ51OWTMrzyE/4je34Oxhw.5xxp3Es7Ke32W. Grund, warum ich versucht habe zu bearbeiten: Es war mir unklar, ob "2 Zeichen funktionieren" eine Ziffer oder ein Hex oder etwas war, das getestet werden musste. Hier ist das Testergebnis für alle anderen, damit Sie es nicht selbst ausprobieren müssen.
Luc
2

Kurzfassung

Die Anzahl der Iterationen, für die mindestens 250 ms berechnet werden müssen

Lange Version

Bei der Erstveröffentlichung von BCrypt im Jahr 1999 wurden die Standardkostenfaktoren ihrer Implementierung aufgelistet:

  • normaler Benutzer: 6
  • Superuser: 8

Ein Verschlüsselungspreis von 6 bedeutet 64 Runden (2 6 = 64).

Sie bemerken auch:

Natürlich sollten die Kosten, die die Menschen wählen, von Zeit zu Zeit neu bewertet werden

  • Zum Zeitpunkt der Bereitstellung im Jahr 1976 konnte die Krypta weniger als 4 Kennwörter pro Sekunde hashen. (250 ms pro Passwort)
  • Im Jahr 1977 konnte auf einem VAX-11/780 die Krypta (MD5) etwa 3,6 Mal pro Sekunde ausgewertet werden. (277 ms pro Passwort)

Das gibt Ihnen einen Eindruck von den Verzögerungen, die die ursprünglichen Implementierer beim Schreiben in Betracht gezogen haben:

  • ~ 250 ms für normale Benutzer
  • ~ 1 Sekunde für Superuser.

Aber je länger Sie stehen können, desto besser. Jede BCrypt-Implementierung, die ich gesehen habe, wird 10als Standardkosten verwendet. Und meine Implementierung hat das genutzt. Ich glaube, es ist Zeit für mich, die Standardkosten auf 12 zu erhöhen.

Wir haben beschlossen, nicht weniger als 250 ms pro Hash anzuvisieren.

Mein Desktop-PC ist eine Intel Core i7-2700K-CPU mit 3,50 GHz. Ich habe ursprünglich eine BCrypt-Implementierung am 23.01.2014 bewertet:

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 |

Geben Sie hier die Bildbeschreibung ein

Zukunftssicherheit

Anstatt eine feste Konstante zu haben, sollte es ein festes Minimum sein .

Anstatt Ihre Passwort-Hash-Funktion zu haben, seien Sie:

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

es sollte so etwas sein wie:

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;
}

Und im Idealfall ist dies Teil der BCrypt-Bibliothek aller Benutzer. Anstatt sich darauf zu verlassen, dass Benutzer der Bibliothek die Kosten regelmäßig erhöhen, erhöhen sich die Kosten regelmäßig von selbst.

Ian Boyd
quelle