it-swarm-eu.dev

Was ist mit PBKDF2 eine optimale Hash-Größe in Bytes? Was ist mit der Größe des Salzes?

Beim Erstellen eines Hashs mit PBKDF2 kann der Entwickler die Größe des Hashs auswählen. Ist länger immer besser? Und was ist mit der Größe des zufälligen Salzes? Sollte das die gleiche Größe wie der Hash haben?

EDIT: Besonders beim Hashing von Passwörtern.

27
blesh

Für die Hash-Funktion möchten Sie eine Funktion verwenden, für die der effizienteste Plattformtyp (derjenige, der mehr Hash-Berechnungen pro Sekunde und pro Dollar erzeugt) die Maschine ist, die Sie verwenden möchten (d. H. Einen PC). Das liegt daran, dass Sie sich mit dem Angreifer in einem Waffenrennen befinden und der Angreifer andere Arten von Hardware kaufen kann, um einen Vorteil gegenüber Ihnen zu erzielen (z. B. eine GPU). GPUs sind sehr gut in 32-Bit-Arithmetik, aber nicht in 64-Bit-Arithmetik, während ein PC (im 64-Bit-Modus) in letzterem Fall ziemlich schnell ist.

Verwenden Sie daher eine Hash-Funktion, die mit 64-Bit-Arithmetikoperationen ausgeführt wird. Dies zeigt auf SHA-512 .

PBKDF2 ist eine Schlüsselableitungsfunktion : Es wird eine Ausgabe mit konfigurierbarer Größe erzeugt. Für das Hashing von Passwörtern soll die Größe groß genug sein, um generische Preimage-Angriffe abzuwehren (d. H. Zufällige Passwörter zu versuchen, bis eine Übereinstimmung gefunden wird). Dies würde beispielsweise mindestens 80 Bit Ausgabe erfordern. Wenn auch nur, um die Sicherheit für Unachtsame und auch für die Ästhetik überzeugender zu gestalten, wählen Sie die nächste Potenz von 2: eine 128-Bit-Ausgabe . Es ist nicht sinnvoll, darüber hinauszugehen.

Das Salz muss einzigartig - so einzigartig wie möglich sein. Eine einfache Möglichkeit, eindeutige Salzwerte zu erzielen, besteht darin, Salze mit einem kryptografisch starkes PRNG zu erzeugen: Die Wahrscheinlichkeit, einen Salzwert wiederzuverwenden, ist ausreichend niedrig, um vernachlässigt zu werden, wenn diese zufälligen Salze groß genug und "groß genug" sind "bedeutet" 128 Bit ". Verwenden Sie also zufällige 128-Bit-Salze .

Persönlich bin ich bevorzuge bcrypt gegenüber PBKDF2 für das Passwort-Hashing.

24
Thomas Pornin

Gemäß dem PBKDF2-Standard beträgt die empfohlene Mindestgröße für das Salz 64 Bit, obwohl ich persönlich 128 Bit oder mehr für einen angemessenen Sicherheitsspielraum empfehlen würde. Die Größe des Salzes ist unabhängig von Ihrer Wahl des Hash.

Aus Sicherheitsgründen empfehle ich, eine abgeleitete Schlüssellänge von mindestens der gleichen Größe der Salzausgabe mit mindestens 256 Bit zu wählen. Jede Hash-Größe von weniger als 256 Bit liegt ohnehin unterhalb der Sicherheitsgrenze der meisten modernen Hash-Funktionen.

Die Auswahl einer abgeleiteten Schlüssellänge, die kleiner als die Ausgabelänge der Hash-Funktion ist, ist wenig sinnvoll, es sei denn, Sie verwenden den Schlüssel für eine Blockverschlüsselung, die einen Schlüssel dieser Größe nicht verarbeiten kann.

In Bezug auf optimale Sicherheit würde ich SHA-512 als PRF vorschlagen, mit einem abgeleiteten 512-Bit-Schlüssel, einem 128-Bit-Salt und so vielen Iterationen, wie Ihre Situation rechtfertigen kann.

11
Polynomial

Wenn Ihre bevorzugte Plattform .NET ist, gibt es einen OWASP-Artikel, der speziell der Klasse Rfc2898DeriveBytes gewidmet ist. Speziell beachten (Schwerpunkt Mine):

Die integrierte .NET-Implementierung von Rfc2898DeriveBytes beschränkt den Benutzer auf eine psudorandom-Funktion - HMAC mit SHA-1 . Dies ist heute in den meisten Szenarien akzeptabel, aber in Zukunft ist möglicherweise eine komplexere Hashing-Funktion erforderlich.

Wenn Sie PBKDF2 für die Kennwortspeicherung verwenden, sollten Sie niemals mehr Bits als die Größe der Basis-Hash-Funktion ausgeben. Bei PBKDF2-SHA1 sind dies 160 Bit oder 20 Bytes . Die Ausgabe von mehr Bits macht den Hash nicht sicherer, kostet den Verteidiger jedoch viel mehr Zeit, ohne den Angreifer zu kosten. Ein Angreifer vergleicht nur die erste Ausgabe mit Hash-Funktionsgröße und spart so Zeit, um das Zurücksetzen der PBKDF2-Ausgabe zu generieren.

Sie haben auch ein Codebeispiel, das ich gemäß den Anweisungen der anderen Antworten angepasst habe:

public static string Hash(string str)
{
    // Generate the hash, with an automatic 16 byte salt
    using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(str, 16))
    {
        rfc2898DeriveBytes .IterationCount = 10000 // or whatever you can afford
        byte[] hash = rfc2898DeriveBytes.GetBytes(20);
        byte[] salt = rfc2898DeriveBytes.Salt;
        return Convert.ToBase64String(salt) + "|" + Convert.ToBase64String(hash);
    }
}
4
Ohad Schneider