Wie benutze ich scrypt um Hash für Passwort und Salz in Python zu generieren?

8

Ich möchte scrypt verwenden, um einen Hash für die Passwörter und Salze meiner Benutzer zu erstellen. Ich habe zwei gefunden referenzen , aber es gibt Dinge, die ich nicht verstehe.

Sie benutzen die scrypt Verschlüsselungs- und Entschlüsselungsfunktionen. Einer verschlüsselt eine zufällige Zeichenfolge und der andere verschlüsselt das Salz (was falsch aussieht, da nur das Passwort und nicht das Salz für die Entschlüsselung verwendet wird). Es sieht so aus, als ob die Entschlüsselungsfunktion verwendet wird, um das Passwort / salt als Nebeneffekt der Entschlüsselung zu validieren.

Basierend auf dem Wenigen, das ich verstehe, will ich eine Schlüsselableitungsfunktion (KDF) anstelle von Verschlüsselung / Entschlüsselung, und die KDF wird wahrscheinlich von scrypt für die Verschlüsselung / Entschlüsselung erzeugt und verwendet. Die eigentliche KDF wird hinter den Kulissen verwendet und ich bin besorgt, dass das blinde Befolgen dieser Beispiele zu einem Fehler führen wird. Wenn die scrypt Verschlüsseln / Entschlüsseln Funktionen verwendet werden, um das Passwort zu generieren und zu überprüfen, verstehe ich nicht die Rolle der Zeichenfolge verschlüsselt werden. Ist der Inhalt oder die Länge wichtig?

    
Mitch 30.11.2012, 23:06
quelle

2 Antworten

10

Sie haben Recht - die Scrypt-Funktionen, mit denen die beiden Links arbeiten, sind das Verschlüsselungs-Dienstprogramm scrypt, nicht das zugrunde liegende kdf. Ich habe langsam daran gearbeitet, einen eigenständigen scrypt-basierten Passwort-Hash für Python zu erstellen, und bin selbst auf dieses Problem gestoßen.

Das Dienstprogramm scrypt file macht folgendes: wählt die für Ihr System spezifischen scrpt's n / r / p Parameter aus. der Parameter "min time". Es erzeugt dann ein 32-Byte-Salz und ruft dann scrypt(n,r,p,salt,pwd) auf, um einen 64-Byte-Schlüssel zu erstellen. Die binäre Zeichenfolge, die das Tool zurückgibt, setzt sich zusammen aus: 1) einem Header, der n, r, p Werte enthält, und dem in binär codierten Salz; 2) eine sha256 Prüfsumme des Headers; und 3) eine hmac-sha256 signierte Kopie der Prüfsumme, wobei die ersten 32 Bytes des Schlüssels verwendet werden. Anschließend verwendet es die verbleibenden 32 Byte des AES-Schlüssels zum Verschlüsseln der Eingabedaten.

Es gibt ein paar Implikationen, die ich sehen kann:

  1. Die Eingabedaten sind bedeutungslos, da sie sich nicht auf das verwendete Salz auswirken, und encrypt () generiert jedes Mal ein neues Salz.

  2. Sie können die Arbeitslast n, r, p nicht manuell oder auf andere Weise als den unbequemen Parameter min-time konfigurieren. Das ist nicht unsicher, aber es ist eine ziemlich umständliche Art, den Arbeitsfaktor zu kontrollieren.

  3. Nach dem Entschlüsselungsanruf wird der Schlüssel neu generiert und mit dem hmac verglichen. Wenn Ihr Passwort falsch ist, wird es alles zurückweisen - aber wenn es richtig ist, wird es mit auch fortgesetzt entschlüsseln Sie das Datenpaket. Dies ist eine Menge zusätzlicher Arbeit, die der Angreifer nicht leisten muss - er muss nicht einmal 64 Bytes ableiten, nur die 32, die benötigt werden, um die Signatur zu überprüfen. Dieses Problem macht es nicht unsicher , aber die Arbeit des Angreifers ist niemals wünschenswert.

  4. Es gibt keine Möglichkeit, den Salt Key, die abgeleitete Schlüsselgröße usw. zu konfigurieren. Die aktuellen Werte sind nicht so schlecht, aber trotzdem ist es nicht ideal.

  5. Die maximale Zeitbegrenzung des Entschlüsselungsdienstprogramms ist falsch für das Hashing von Kennwörtern - jedes Mal, wenn Entschlüsselung aufgerufen wird, schätzt es die Geschwindigkeit Ihres Systems ab und "rät", ob es den Schlüssel innerhalb der maximalen Zeit berechnen kann - Das ist der Aufwand, den Ihr Angreifer nicht zu tun braucht (siehe # 3), aber es bedeutet auch, dass die Entschlüsselung unter schwerer Systemlast die Kennwörter ablehnen kann.

  6. Ich bin mir nicht sicher, warum Colin Percival die kdf & amp; Parameter-Auswahl Code Teil der öffentlichen API, aber es ist in der Tat explizit markiert "privat" im Quellcode - nicht sogar für die Verknüpfung exportiert. Dies macht mich zögern, gerade ohne viel mehr Studium direkt zugreifen.

Alles in allem ist ein nettes Hash-Format erforderlich, das scrypt speichern kann, und eine Implementierung, die den zugrunde liegenden kdf- und Parameter-Auswahl-Algorithmus freilegt. Ich arbeite gerade selbst daran, passlib , aber es hat nicht viel Aufmerksamkeit bekommen :(

Nur zur Schlussfolgerung - die Anweisungen auf dieser Seite sind "ok", ich würde nur eine leere Zeichenfolge als Dateiinhalt verwenden und mir des zusätzlichen Aufwands und der Probleme bewusst sein.

    
Eli Collins 01.12.2012, 20:17
quelle
4

Beide Referenzen haben es völlig falsch verstanden. Mist nicht mit encrypt und decrypt : benutze einfach hash

Die KDF ist nicht direkt verfügbar, aber hash ist nahe genug. (In der Tat scheint es mir sogar besser zu sein, weil es die Füllung eines PBKDF2-Sandwiches mischt.)

Dieser Beispielcode funktioniert sowohl mit python2.7 als auch mit python3.2. Es verwendet PyCrypto, passlib und py-scrypt, aber nur braucht py-scrypt.

Sie sollten eine Constant-Time-Vergleichsfunktion wie passlib.utils.consteq verwenden, um Timing-Attacken zu minimieren.

Sie möchten auch die Parameter sorgfältig auswählen. Die Standardwerte logN = 14, r = 8, p = 1 bedeuten 1 "Runde" mit 16 MiB Speicher. Auf einem Server wollen Sie wahrscheinlich etwas mehr wie 10,8,8 - weniger RAM, mehr CPU. Sie sollten es auf Ihrer Hardware unter Ihrer erwarteten Belastung abmessen.

    
Terrel Shumway 26.09.2013 14:26
quelle