Wie funktioniert ein Zufallsstring-Generator in PHP eigentlich? Ein Blick unter die Haube
Haben Sie sich jemals gefragt, was passiert, wenn Sie auf einer Website auf „Passwort generieren“ klicken? Oder wenn das System eine eindeutige Kennung für Ihre Sitzung erstellt? In neun von zehn Fällen steckt dahinter ein Zufallsstring-Generator in PHP. Es scheint einfach: Man nehme ein Zeichen-Array, mische es und gebe das Ergebnis aus. Aber der Teufel steckt, wie immer, im Detail.
Auf Stack Overflow hat die Frage „PHP random string generator“ tausende Aufrufe. Das ist kein Zufall. Anfänger schreiben Fahrräder mit rand(), Erfahrene verwenden random_int(), und Gurus diskutieren über Entropie. Lassen Sie uns verstehen, wie es wirklich funktioniert, und unseren eigenen idealen Generator schreiben.
Warum ist rand() böse? (Spoiler: Vorhersagbarkeit)
Die beliebteste „Anfänger“-Methode ist die Verwendung von rand() in einer Schleife:
<?phpfunction generateRandomString($length = 10) { $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $charactersLength = strlen($characters); $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } return $randomString;}echo generateRandomString(); // Ausgabe: "aB3kL9xQ2m"?>Der Code funktioniert. Aber nur, wenn Ihnen Sicherheit egal ist. Die Funktion rand() verwendet einen linearen Kongruenzgenerator (LCG). Dies ist ein deterministischer Algorithmus: Kennt man den aktuellen Zustand, kann man alle folgenden Zahlen vorhersagen. Außerdem wird rand() standardmäßig mit 1 initialisiert, wenn Sie nicht srand() aufgerufen haben. Und wenn Sie es aufrufen, wird der Seed oft von time() abgeleitet, was nur 2-3 Millionen Möglichkeiten ergibt. Das Durchprobieren dauert Sekunden.
Fazit: rand() ist für Spiele und die zufällige Auswahl von Avataren geeignet, aber absolut ungeeignet für die Generierung von Tokens, Passwörtern oder API-Schlüsseln.
Lernen Sie mt_rand() kennen – schneller, aber nicht sicherer
In PHP 4 wurde mt_rand() eingeführt, basierend auf dem Mersenne-Twister. Er ist schneller und hat eine bessere Periode (2^19937 gegenüber 2^31 bei rand). Viele verwenden ihn immer noch als „fortgeschrittene“ Version:
<?phpfunction generateTokenMtRand($length = 32) { $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $token = ''; for ($i = 0; $i < $length; $i++) { $token .= $chars[mt_rand(0, strlen($chars) - 1)]; } return $token;}?>Aber auch hier gibt es einen Haken. Der Mersenne-Twister ist kryptographisch nicht sicher. Aus einer Sequenz von 624 generierten Zahlen kann der interne Zustand des Generators wiederhergestellt und alle zukünftigen Werte vorhergesagt werden. Für einen Angriff auf ein Passwort-Reset-Token ist das mehr als ausreichend.
Die Moral: mt_rand() ist eine ausgezeichnete Wahl für Simulationen und Tests, aber nicht für die Sicherheit.
Die heilige Dreifaltigkeit: random_int(), CSPRNG und Entropie
Seit PHP 7.0 haben wir random_int() und random_bytes(). Dies sind kryptographisch sichere Pseudozufallszahlengeneratoren (CSPRNG). Was bedeutet das in der Praxis?
- Entropie: PHP sammelt „Rauschen“ aus dem System: Zeit zwischen Tastendrücken, Mausbewegungen, Netzwerkpakete, Festplatteninterrupts. Unter Linux wird
/dev/urandomverwendet, unter WindowsCryptGenRandom. - Unvorhersagbarkeit: Selbst wenn man den Algorithmus kennt, kann man den Seed nicht wiederherstellen oder die nächste Zahl vorhersagen.
- Gleichmäßige Verteilung: Jedes Byte tritt mit einer Wahrscheinlichkeit von genau 1/256 auf.
So sieht ein korrekter Zufallsstring-Generator in PHP aus