it-swarm.com.de

md5 (uniqid) macht Sinn für zufällige eindeutige Token?

Ich möchte einen Token-Generator erstellen, der Token generiert, die vom Benutzer nicht erraten werden können und die immer noch eindeutig sind (für das Zurücksetzen von Passwörtern und Bestätigungscodes).

Ich sehe diesen Code oft. macht das Sinn?

md5(uniqid(Rand(), true));

Nach einem Kommentaruniqid($prefix, $moreEntopy = true) ergibt

die ersten 8 hexadezimalen Zeichen = Unixtime, die letzten 5 hexadezimalen Zeichen = Mikrosekunden.

Ich weiß nicht, wie der $prefix- Parameter behandelt wird.

Wenn Sie also das Flag $ moreEntopy nicht auf true setzen, erhalten Sie ein vorhersehbares Ergebnis.


FRAGE: Aber wenn wir uniqid mit $moreEntopy verwenden, was bringt es uns, wenn es mit md5 hasht? Ist es besser als:

md5(mt_Rand())

edit1: Ich speichere dieses Token in einer Datenbankspalte mit einem eindeutigen Index, damit ich Spalten erkennen kann. Könnte von Interesse sein /

33
Exception e

Rand () ist ein Sicherheitsrisiko und sollte niemals zum Generieren eines Sicherheitstokens verwendet werden: Rand () vs mt_Rand () (Schauen Sie sich die "statischen" Bilder an). Keine dieser Methoden zur Erzeugung von Zufallszahlen ist jedoch kryptographisch sicher. Um sichere Sicherheiten zu erzeugen, muss eine Anwendung auf ein CSPRNG zugreifen, das von der Plattform, dem Betriebssystem oder dem Hardwaremodul bereitgestellt wird. 

In einer Webanwendung ist eine gute Quelle für sichere Geheimnisse der nicht blockierende Zugriff auf einen Entropiepool wie /dev/urandom. Ab PHP 5.3 können PHP - Anwendungen openssl_random_pseudo_bytes() verwenden, und die Openssl-Bibliothek wählt die beste Entropiequelle basierend auf Ihrem Betriebssystem aus. Unter Linux bedeutet dies, dass die Anwendung /dev/urandom verwendet. Dieser Code-Snip von Scott ist ziemlich gut :

function crypto_Rand_secure($min, $max) {
        $range = $max - $min;
        if ($range < 0) return $min; // not so random...
        $log = log($range, 2);
        $bytes = (int) ($log / 8) + 1; // length in bytes
        $bits = (int) $log + 1; // length in bits
        $filter = (int) (1 << $bits) - 1; // set all lower bits to 1
        do {
            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
            $rnd = $rnd & $filter; // discard irrelevant bits
        } while ($rnd >= $range);
        return $min + $rnd;
}

function getToken($length=32){
    $token = "";
    $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
    $codeAlphabet.= "0123456789";
    for($i=0;$i<$length;$i++){
        $token .= $codeAlphabet[crypto_Rand_secure(0,strlen($codeAlphabet))];
    }
    return $token;
}
43
rook

Dies ist eine Kopie einer anderen Frage, die ich vor ein paar Monaten gestellt hatte. Hier ist ein Link zu der Frage und meiner Antwort: https://stackoverflow.com/a/13733588/1698153 .

Ich stimme der akzeptierten Antwort nicht zu. Laut PHPs eigener Website "[uniqid] does not generate cryptographically secure tokens, in fact without being passed any additional parameters the return value is little different from microtime(). If you need to generate cryptographically secure tokens use openssl_random_pseudo_bytes()."

Ich glaube nicht, dass die Antwort klarer sein könnte, uniqidist nicht sicher. 

21
Scott

Ich weiß, dass die Frage alt ist, aber sie wird in Google angezeigt, also ...

Wie bereits erwähnt, garantieren Rand(), mt_Rand() oder uniqid() keine Eindeutigkeit. Auch openssl_random_pseudo_bytes() sollte nicht verwendet werden, da es veraltete Funktionen von OpenSSL .

Was Sie verwenden sollten, um zufälligen Hash (wie md5) zu generieren, ist random_bytes () (eingeführt in PHP7). So generieren Sie einen Hash mit derselben Länge wie MD5:

bin2hex(random_bytes(16));

Wenn Sie PHP 5.x verwenden, können Sie diese Funktion mit random_compat library erhalten.

5

Definieren Sie "eindeutig". Wenn Sie meinen, dass zwei Token nicht denselben Wert haben können, reicht das Hashing nicht aus - es sollte mit einem Eindeutigkeitstest gesichert werden. Die Tatsache, dass Sie den Hash-Algorithmus mit eindeutigen Eingaben versorgen, garantiert keine eindeutigen Ausgaben.

1
M.A. Hanin

Um Ihre Frage zu beantworten, besteht das Problem darin, dass Sie keinen Generator haben können, der zufällig garantiert und von sich aus eindeutig ist, d. H. md5(mt_Rand()) kann zu Duplikaten führen. Was Sie wollen, ist "zufällig erscheinende" einzigartige Werte. uniqid gibt die eindeutige ID an, Rand () fügt eine Zufallszahl hinzu, was das Schätzen noch schwieriger macht, md5 maskiert das Ergebnis und macht es noch schwerer zu erraten. Nichts ist unvorstellbar. Wir müssen es nur so schwer machen, dass sie es nicht einmal versuchen wollen.

1
webbiedave

Ich bin vor einigen Jahren auf eine interessante Idee gestoßen.
Speichern von zwei Hashwerten in der Dateibasis, einer mit md5 ($ a) und der andere mit sha ($ a). Dann prüfen, ob beide Werte korrekt sind. Punkt ist, wenn der Angreifer Ihr MD5 () gebrochen hat, kann er Ihr MD5 UND SHA in der nahen Zukunft nicht brechen.
Problem ist: Wie kann dieses Konzept mit der Token-Generierung verwendet werden, die für Ihr Problem benötigt wird?

1
gogink

Erstens besteht der Umfang dieser Art von Prozedur darin, einen Schlüssel/Hash/Code zu erstellen, der für eine gegebene Datenbank eindeutig ist. Es ist unmöglich, zu einem bestimmten Zeitpunkt etwas Einzigartiges für die ganze Welt zu erstellen ... Sie sollten jedoch eine einfache, sichtbare Zeichenfolge mit einem benutzerdefinierten Alphabet erstellen und den erstellten Code anhand Ihrer Datenbank (Tabelle) prüfen. Wenn diese Zeichenfolge eindeutig ist, wenden Sie eine md5() an, die von niemandem oder irgendeinem Skript erraten werden kann. Ich weiß, wenn Sie tief in die Theorie der kryptografischen Generierung einsteigen, finden Sie viele Erklärungen zu dieser Art der Codegenerierung, aber wenn Sie sie in die Praxis umsetzen, ist das nicht so kompliziert.

Hier ist der Code, den ich verwende, um einen einfachen 10-stelligen eindeutigen Code zu generieren.

$alphabet = "[email protected]#dD5%eE6^fF7&gG8*hH9(iI0)jJ4-kK=+lL[mM]nN{oO}pP\qQ/rR,sS.tT?uUvV>xX~yY|zZ`wW$";
$code = '';
$alplhaLenght = strlen($alphabet )-1;
for ($i = 1; $i <= 10; $i++) {
    $n = Rand(1, $alplhaLenght );
    $code .= $alphabet [$n];
}

Und hier sind einige generierte Codes, obwohl Sie es selbst ausführen können, um zu sehen, dass es funktioniert:

SpQ0T0tyO% 
Uwn [MU] [. 
D | [ROt + Cd @ 
O6I | w38TRe 

Natürlich kann es eine Menge "Verbesserungen" geben, die darauf angewendet werden können, um es "komplizierter" zu machen, aber wenn Sie eine md5() anwenden, wird dies zu "Unüberlegbar". :)

0
Lucian Minea