7 Stimmen

Helfen Sie mir pack(), openssl_random_pseudo_bytes() und mt_rand() für das Salzen von Passwörtern zu verstehen

Ich baue eine Anwendung, die eine Benutzerbasis haben wird, und ich bin an dem Punkt der Sicherung der Anmeldung. Ich bin ziemlich neu in der Programmierung (und PHP), aber meine Bemühungen bisher haben darauf hingewiesen, mit Crypt() und ein Blowfish-gehashtes Salz.

Bevor ich fortfahre, möchte ich klarstellen, dass Ich bin nicht an phpass interessiert. zu diesem Zeitpunkt.

Innerhalb der crypt() Dokumentation hat ein Benutzer vor kurzem folgendes gepostet:

<?php 
   $salt = substr(str_replace('+', '.', base64_encode(pack('N4', mt_rand(), mt_rand(), mt_rand(), mt_rand()))), 0, 22); 
?>

Es ist für die Verwendung auf Systemen vorgesehen wo mt_getrandmax() == 2147483647.

Das erzeugte Salz wird 128 Länge, wird auf 132 Bit aufgefüllt und dann in 22 base64-Zeichen ausgedrückt. (CRYPT_BLOWFISH verwendet 128 Bits nur für für das Salt, obwohl 132 Bits in 22 Bits in 22 base64-Zeichen enthalten sind. Wenn Sie die CRYPT_BLOWFISH-Eingabe und -Ausgabe untersuchen Ausgabe untersuchen, können Sie sehen, dass es die die letzten vier Bits bei der Eingabe ignoriert und bei der Ausgabe auf Null setzt).

N vier 32-Bit-Wörter, die von mt mt_getrandmax == 2^31), so dass nur 124 der der 128 Bits pseudozufällig sein werden. I fand das akzeptabel für meine Anwendung akzeptabel.

Ich habe meinen Server getestet, und tatsächlich gibt mt_getrandmax() 2147483647 zurück. Ich habe versucht, in der Dokumentation herumzustochern, um zu verstehen, was der obige Code wirklich tut - die pack() Code N4 steht für eine 32-Bit-Zeichenkette (Big-Endian-Bytereihenfolge??), die 4 Mal wiederholt wird... deshalb gibt es wohl auch 4 mt_rand() Argumente.

Was ich nicht verstehe, ist, warum er die + con . und den Zweck von 22 base64-Zeichen (nicht, dass ich ganz verstehe, was base64 ist).

Es wurde mir empfohlen, mich mit folgenden Themen zu befassen openssl_random_pseudo_bytes() für meine zufällige Salzgenerierung, da die vorherige Methode, die ich mir angesehen habe, sich nur auf 1234567890abcdefghijklmnopqrstuvwxyz .

Angeblich gab es einen Fehler vor 5.3.4 verursacht openssl_random_pseudo_bytes() schmerzhaft langsam und verursacht gelegentlich Timeout-Fehler. Ich bin nicht sicher, ob ich versuchen sollte, mit openssl_random_pseudo_bytes() con Crypt() oder etwas Ähnliches wie die obige Methode mit mt_rand() y pack() .

Ich versuche, mehr zu verstehen, wie all diese Elemente funktionieren und was sie konzeptionell tun - anstatt nur eines zu verwenden, ohne es zu verstehen, um mein Ziel zu erreichen; ich versuche zu lernen :P

Kann mir jemand helfen, die verschiedenen Elemente zu verstehen, die hier eine Rolle spielen, oder mich zumindest auf eine Wissensdatenbank verweisen, in der ich darüber lesen kann? Ich denke, die schwierigste Komponente ist das Verständnis der verschiedenen Formate/Terminologie (base64, ascii, hexdec, bit, byte usw.), aber letztendlich auch, wie ich ein einigermaßen sicheres Salt für meine Passwörter bekomme.

11voto

ircmaxell Punkte 159431

Lassen Sie mich zunächst sagen, dass ein Salz unter dem Gesichtspunkt der Erzeugung nichts Besonderes ist. Es ist nur eine weitere zufällige Zeichenkette. Es ist etwas Besonderes in Bezug auf seine Verwendung, aber nicht in Bezug auf seine Erzeugung.

Ihre spezifischen Fragen

  1. Warum ersetzt er + con . ?

    Ich habe keine Ahnung. Vielleicht liegt es daran, dass die + Zeichen kann mit einem Leerzeichen in Urls verwechselt werden. Aber ein Salz sollte niemals in einer URL vorkommen, also ist das wahrscheinlich nicht der Fall.

  2. Was macht base64/hexdec:

    Base64 wandelt einen rohen Bytestrom (jedes Byte hat Werte von 0 bis 255) in eine Base 64-Darstellung um. Es gibt zahlreiche Ressourcen zu diesem Thema, so dass es sich nicht lohnt, näher darauf einzugehen. Lesen Sie der wikipedia-Artikel für weitere Informationen.

    hexdec wandelt eine Hexadezimalzahl (a-f0-9) in eine Dezimalzahl um. Es konvertiert von der Basis 16 zur Basis 10 (nur eine andere Art der Zahlendarstellung).

  3. Was ist ein Bit und ein Byte:

    Ein Bit ist eine einzelne Informationseinheit. Es hat 2 Zustände, 0 oder 1. Ein Byte ist eine Folge von 8 Bits. Ein Byte kann also 256 einzigartige Kombinationen haben. Lesen Wikipedia ...

  4. Was ist ascii

    Es ist ein Zeichensatz. Er stellt ein einzelnes druckbares Zeichen in einem einzelnen 8-Bit-Byte dar. Auch hier würde ich vorschlagen, zu lesen Wikipedia .

Salze im Allgemeinen

Das Ziel einer guten Salzgenerierungsfunktion ist eine große Entropie. Das bedeutet, dass die Anzahl der möglichen Ausgaben so groß wie möglich ist. Jede Methode sollte also eine große Anzahl von Ergebnissen liefern.

Nun müssen Sie festlegen, welche Zeichen für den Salt zulässig sind (da Sie den Salt speichern müssen, um den Hash zu verifizieren). Die bestmöglichen Salts sind Vollbyte-Zahlen und nicht nur anzeigbare Zeichen. Sie werden diese nicht sinnvoll anzeigen können, aber Sie müssen sie auch nicht anzeigen. Außerdem können Sie für die Speicherung immer Folgendes verwenden base64_encode es.

Als Nächstes müssen Sie festlegen, wie groß das Salz sein soll. Je größer das Salz ist, desto besser. Ein 32-Zeichen-Salz ist akzeptabel, aber ein 128-Zeichen-Salz ist besser. Die Größe des Salzes und die Anzahl der Optionen pro Zeichen bestimmen die Anzahl der Möglichkeiten, die es gibt. Einige gängige Kombinationen:

Hex, 32 characters: 2e38 possibilities
Hex, 128 characters: 1e154 possibilities
Full Byte, 32 characters: 1e77 possibilities
Full Byte, 128 characters: 1e308 possibilities

Nun müssen Sie das Salz erzeugen. Der Schlüssel dazu ist, so viele Zufallsaufrufe wie nötig zu tätigen, um die Entropie aufzufüllen. Sie können dies auf verschiedene Weise tun:

  • Systemabhängig (funktioniert nur unter *nix, aber beste Entropie):

    $f = fopen('/dev/urandom', 'r');
    $seed = fgets($f, $characters); // note that this will always return full bytes
    fclose($f);
  • Bibliotheksabhängig (gut, erfordert aber die Installation von OpenSSL)

    $seed = openssl_random_pseudo_bytes($characters);
  • Fallback

    $seed = '';
    for ($i = 0; $i < $characters; $i++) {
        $seed .= chr(mt_rand(0, 255));
    }

Nun müssen Sie sie in das gewünschte Ausgabeformat konvertieren.

  • Hex (a-f0-9):

    $out = '';
    for ($i = 0, $len = strlen($seed); $i < $len; $i++) {
        $num = ord($seed);
        $out .= dechex(floor($num / 16)) . dechex($num % 16);
    }
  • Basis36 (a-z0-9):

    $out = '';
    for ($i = 0, $len = strlen($seed); $i < $len; $i++) {
        $num = ord($seed);
        $out .= base_convert($num, 10, 36);
    }
  • Base64 (a-zA-Z0-9+=):

    $out = base64_encode($seed);
  • Volles Byte:

    Das ist nicht notwendig, da es bereits in diesem Format vorliegt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X