ersetzen rand() mit openssl_random_pseudo_bytes()
Ich brauche einen Ersatz für PHP rand()
- Funktion, die verwendet einen kryptographisch starken Zufallszahlengenerator.
Den openssl_random_pseudo_bytes()
Funktion bekommt man Zugriff auf die starken random number generator, aber es gibt seine Daten als byte-string. Stattdessen muss eine ganze Zahl zwischen 0 und X.
Ich vorstellen, der Schlüssel ist, um die Ausgabe openssl_random_pseudo_bytes()
in ein integer ist, dann können Sie Mathe auf, dass Sie es müssen. Ich kann mir denken, ein paar "brute-force" Möglichkeiten der Umwandlung von einem byte-string in einen integer, aber ich hatte gehofft, für etwas ... elegant.
- mt_rand() geben viel bessere Qualität der Zufallszahlen als rand(), aber es ist nicht kryptografisch starke entweder.
- Vorsicht, diese Antwort ist falsch. um genauer zu sein, die "% $ - range" - Teil ist falsch. Nehmen Sie Folgendes Szenario: Sie erstellen wollen, zahlen zwischen 1 (einschließlich) und 4 (ausschließlich) (da Sie max-min). $range = 3. Nun 3 nicht gleichmäßig aufzuteilen ist in 2^8 was bedeutet, dass 1 geht häufiger zu sein als 3. Seien Sie sehr vorsichtig, Sie wollte, einen sicheren Zufallszahlengenerator aber versehentlich machte es unsicher, dies ist, warum es wird empfohlen, zur Verwendung der vorhandenen Implementierungen.
- Wenn das richtig verstehe, in ein 8-bit-Sortiment erhalten Sie 85 Sätze von [1,2,3] sowie ein [1,] übrig, dass eine "1" über 1.17% häufiger auftauchen als "2" oder "3", richtig? Wie würden Sie dieses problem lösen? Offensichtlich mit einer vorhandenen Implementierung eine option nicht, oder ich hätte nicht die Frage gestellt.
$num = hexdec(bin2hex(openssl_random_pseudo_bytes($length,$s))); $max = pow(2, 8*length); //for clarity, you can replace with a faster bit shift $remainder = $max % $range; $max = $max - $remainder; if ($num > $max){ return crypto_rand($min,$max); } return $min + ($num % $range);
- In Worten, Sie im wesentlichen erhalten die höchste Zahl, die gleichmäßig teilt in Ihrem Bereich (auch im Bereich der random number generator), und wenn der Wert höher ist, müssen Sie die Funktion erneut ausführen.
- Ich denke, Sie sollte sich ändern: $max = $max - $Rest; bis $max = $max - $Rest - 1; - sonst bekommt man die ungleiche Verteilung in Richtung auf den ersten Wert in der Reihe.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Mit gelieferten Anregungen, ich habe eine drop-in-Ersatz für rand (), die OpenSSL verwenden. Ich werde es hier für die Nachwelt.
Den $pedantisch option gibt bias-freie Ergebnisse, indem Sie erst auf, wenn sich die Ergebnisse nicht gleichmäßig verteilt über die mögliche Reichweite.
random_int()
in PHP 5 Projekte, und unser Ansatz funktioniert auch, wenn$max - $min > PHP_INT_MAX
. Sie finden unsere Bemühungen auf Github unter random_compat, wenn Sie möchten, zu Wiegen, mit Ihrer eigenen Perspektive.Die manual-Seite für
openssl_random_pseudo_bytes()
hat ein Beispiel, ich denke, Sie wollen. Sie können einfach anrufenbin2hex()
auf die Ausgabe vonopenssl_random_pseudo_bytes()
zu konvertieren, um eine hexadezimale Zahl, dannhexdec()
auf, dass der Wert konvertieren in decimal.In diesem Punkt kann man tun, was Mathematik, die Sie wollen, um einen Wert in den Bereich, den Sie brauchen. Die andere (cheater) - option, die Sie haben könnten ist, führen Sie einen system-Befehl zum generieren einer zufälligen Zahl - es sind ein paar gute Optionen für die Zufallszahlen-Generatoren für verschiedene Betriebssysteme verfügbar online.
Hier eine version von den oben genannten Lösungen, die nicht mit rekursiven Funktionsaufrufen:
Seit PHP 7 ist jetzt der einfachste Weg, dieses problem zu lösen, ist zu ersetzen Sie alle Instanzen von
mt_rand
mitrandom_int
.(Vorausgesetzt, Sie aktualisiert haben, ist, dass.)
gut, nur mit hexdec auf das Ergebnis openssl_random_pseudo_bytes und Sie erhalten Ihren ganze Zahl. Es ist so elegant wie es geht 🙂
Der einfachste Weg, dies zu tun (und die meisten sicher aus all den Optionen hier), ist die Verwendung CryptoLib die eine randomInt Funktion, bietet ein drop-in replacement für den rand.
Ersten download-CryptoLib aus und kleben Sie es in Ihr Projekt: https://github.com/IcyApril/CryptoLib
Zwei, fallen in diesem code. ersetzen "path/to/mit dem Verzeichnis von cryptolib.php und die" min /max " mit Ihren minimalen und maximalen zahlen:
Die CryptoLib die vollständige Dokumentation ist unter: https://cryptolib.ju.je/