Zufallsstring
crille
- php
Hallo SELFHTMLer!
Ich erzeuge momentan per md5(mt_rand()) einen Zufallsstring, der 32 Zeichen lang und hexadezimal ist. Ich würde allerdings lieber einen String erzeugen, der sämtliche URL-kompatiblen Zeichen enthält, also 0-9, a-z, A-Z, "-", "," usw.
Bei meiner Recherche bin ich auf die Erzeugung von Sessions gestoßen, wo man per session.hash_bits_per_character angeben kann, welche Zeichen vorkommen sollen.
Also: Gibt es eine (mir noch nicht bekannte) Funktion, mit der ich einen Zufallsstring erzeugen kann, der sämtliche URL-kompatible Zeichen enthält?
Grüße
crille
Hallo crille,
Also: Gibt es eine (mir noch nicht bekannte) Funktion, mit der ich einen Zufallsstring erzeugen kann, der sämtliche URL-kompatible Zeichen enthält?
Wahrscheinlich nicht. Ich würde mir einfach in ein Array alle erlaubten Zeichen packen und dann per Schleife einzeln ein zufälliges Element aus dem Array an einen Leerstring anhängen.
Jonathan
Hallo Jonathan,
Also: Gibt es eine (mir noch nicht bekannte) Funktion, mit der ich einen Zufallsstring erzeugen kann, der sämtliche URL-kompatible Zeichen enthält?
Wahrscheinlich nicht. Ich würde mir einfach in ein Array alle erlaubten Zeichen packen und dann per Schleife einzeln ein zufälliges Element aus dem Array an einen Leerstring anhängen.
Dazu braucht man noch nicht mal ein Array - ein einfacher String mit allen gültigen Zeichen reicht aus. :-)
Den zerlegt man dann einfach mit str_split() in ein Array.
Grüße
Marc Reichelt || http://www.marcreichelt.de/
Hello Marc,
und jetzt noch meinen Senf dazu...
Den zerlegt man dann einfach mit str_split() in ein Array.
Man muss ihn gar nicht erst zerlegen, weil PHP einen String bereits als Array (klassischer Art) behandelt. Der Zugriff, den Alex https://forum.selfhtml.org/?t=158915&m=1033643 beschreiben hat, geht also auch ohne substring-Funktion.
for($i=0;$i<$stringlaenge;$i++)
{
$zufallsstring .= $zeichen[mt_rand(0, $zeichenlaenge - 1)];
}
Der Direktzugriff ist extrem schnell. Der Aufruf der Funktionen str_split() oder substr() dauert länger. Das ist aber natürlich erst von Interesse, wenn man z.B. Bildmanipulation mittels PHP betreiben will/muss oder ähnlich dateninsive Dinge.
Ich habe aber jetzt noch nicht überlegt/getestet, was passiert, wenn eine komplexe Codierung für die Zeichen des Strings verwendet wird, also z.B. UTF-8.
Allerdings sollen hier ohnehin keine Zeichen aus dem Mehrbyte-Bereich vorkommen...
Harzliche Grüße vom Berg
http://bergpost.annerschbarrich.de
Tom
Hallo Tom,
Man muss ihn gar nicht erst zerlegen, weil PHP einen String bereits als Array (klassischer Art) behandelt. Der Zugriff, den Alex https://forum.selfhtml.org/?t=158915&m=1033643 beschreiben hat, geht also auch ohne substring-Funktion.
for($i=0;$i<$stringlaenge;$i++)
{
$zufallsstring .= $zeichen[mt_rand(0, $zeichenlaenge - 1)];
}
Das wusste ich auch noch, dass es irgendwie einen Direktzugriff auf die einzelnen Zeichen gab - ich wusste nur nicht mehr, wie. :-)
Grüße
Marc Reichelt || http://www.marcreichelt.de/
Hello,
Man muss ihn gar nicht erst zerlegen, weil PHP einen String bereits als Array (klassischer Art) behandelt. Der Zugriff, den Alex https://forum.selfhtml.org/?t=158915&m=1033643 beschreiben hat, geht also auch ohne substring-Funktion.
for($i=0;$i<$stringlaenge;$i++)
{
$zufallsstring .= $zeichen[mt_rand(0, $zeichenlaenge - 1)];
}Das wusste ich auch noch, dass es irgendwie einen Direktzugriff auf die einzelnen Zeichen gab - ich wusste nur nicht mehr, wie. :-)
Ab PHP 6 haben die Entwickler sich auch endlich mit sich selbst geeinigt, dass nur noch die Zeichen [ und ] , also eckige Klammern zur Kenntlichmachung des Dereferenzierers benutzt werden und nicht mehr (auch) { und }, also die geschweiften Klammern, die für die Einleitung eines eigenen Blockes stehen.
Das macht PHP wieder ein Stück erwachsener. ;-)
Harzliche Grüße vom Berg
http://bergpost.annerschbarrich.de
Tom
Hallo Tom,
Der Zugriff, den Alex https://forum.selfhtml.org/?t=158915&m=1033643 beschreiben hat, geht also auch ohne substring-Funktion.
OK, machen wir noch ne nette Funktion draus:
function random_string($length,$characters='abcdefghijklmnopqrstuvwxyz0123456789')
{
$random_string = '';
$characters_length = strlen($characters);
for($i=0;$i<$length;$i++)
{
$random_string .= $characters[mt_rand(0, $characters_length - 1)];
}
return $random_string;
}
Aufzurufen mit:
$zufallsstring = random_string(10); // z.B. "w4pge4ef97"
oder
$zufallsstring = random_string(10,'xyz'); // z.B. "yxyzzxyxzy"
Alex
Hello Alex,
OK, machen wir noch ne nette Funktion draus:
Fein! Ist zwar ein Sektenslogan, aber trotzdem wahr: "starten - durchführen - beenden!"
Ich erlaube mir noch ein paar Anmerkungen dazu.
function random_string($length, $characters = 'abcdefghijklmnopqrstuvwxyz0123456789')
{
$random_string = '';
$characters_length = strlen($characters);
for($i=0;$i<$length;$i++)
{
$random_string .= $characters[mt_rand(0, $characters_length - 1)];
}
return $random_string;
}
>
> Aufzurufen mit:
>
> `$zufallsstring = random_string(10); // z.B. "w4pge4ef97"`
>
$characters muss nicht angegeben werden, da es vom Designer der Funktion (Alex) bereits mit sinnvollen Werten vorbelegt wurde.
Will man einen anderen Wertebereich haben, muss man $characters angeben:
> `$zufallsstring = random_string(10,'xyz'); // ergibt z.B. "yxyzzxyxzy"`
Für den Wertebereich für $characters würde ich dann noch ein paar Konstanten anbieten
CHR\_BASE64 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST+/0123456789";
CHR\_URL\_STRICT = "abcdefghijklmnopqrstuvwxyz-0123456789";
CHR\_ASCII = " ...
usw.
Das Ganze bringt mich nochmals zu der Frage, ob wir nicht eine PHP-Funktionssammlung aufmachen wollen für kleine nutzbringende Funktionen, frei nach dem Schema
- Funktionen, die man haben muss
- Funktionen, die man haben sollte
- Funktionen, die manchmal nützlich sind
- Funktionen, die keiner braucht, die abner troitzdem lutsig sind ;-)
Natürlich mit Erläuterungen und Stichwort-Index dazu und Bewertungssystem.
Viele der nützlichen Funktionensind auch schon in den UCN von <http://www.php.net/manual/en/> aufgeführt. Aber wirklich danach suchen kann man noch nicht.
Wer macht mit?
Harzliche Grüße vom Berg
<http://bergpost.annerschbarrich.de>
Tom
--
Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
Nur selber lernen macht schlau
Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

Hallo,
Also: Gibt es eine (mir noch nicht bekannte) Funktion, mit der ich einen Zufallsstring erzeugen kann, der sämtliche URL-kompatible Zeichen enthält?
Kannst Du Dir einfach selber machen, indem Du die Zeichen vorgibst, die vorkommen dürfen, etwa so:
<?php
// hier meine erlaubten Zeichen:
$zeichen="abcxyz123";
// gewünschte Stringlänge:
$stringlaenge = 10;
// erst mal leeren String erzeugen:
$zufallsstring = '';
// länge des Zeichen-Strings ermitteln:
$zeichenlaenge = strlen($zeichen);
// So oft ein zufälliges Zeichen anhängen bis $stringlaenge erreicht ist:
for($i=0;$i<$stringlaenge;$i++)
{
$zufallsstring.=substr($zeichen,mt_rand(0,$zeichenlaenge-1),1);
}
?>
Alex
Hallo,
Ich erzeuge momentan per md5(mt_rand()) einen Zufallsstring
Achtung, mt_rand() hat nur einen Zahlenbereich von 0 bis 2,1 Mrd (manchmal auch weniger).
Deswegen ist es besser, sofern man die Möglichkeit hat, aus /dev/urandom z.B. 16 Zeichen auslesen oder noch andere Sachen einzubeziehen, wie z.B. verwendeter Speicher etc.
Ich würde allerdings lieber einen String erzeugen, der sämtliche URL-kompatiblen Zeichen enthält, also 0-9, a-z, A-Z, "-", "," usw.
Aus Interesse, darf man Fragen warum?
MFG
Ich würde allerdings lieber einen String erzeugen, der sämtliche URL-kompatiblen Zeichen enthält, also 0-9, a-z, A-Z, "-", "," usw.
Aus Interesse, darf man Fragen warum?
Mein Gedanke war, dass ich alle Zeichen verwenden möchte und nicht "nur" 16 - das erhöht die Kombinationsmöglichkeiten bei einer Länge von 32 Zeichen von 16^32 auf 62^32 (nur 0-9, a-z, A-Z).
Ob ich diese zusätzlichen Kombinationsmöglichkeiten aber überhaupt brauche, wage ich zu bezweifeln... ;o)
Grüße & Besten Dank für die Antworten
crille
Hallo,
Mein Gedanke war, dass ich alle Zeichen verwenden möchte und nicht "nur" 16 - das erhöht die Kombinationsmöglichkeiten bei einer Länge von 32 Zeichen von 16^32 auf 62^32 (nur 0-9, a-z, A-Z).
md5() generiert einen 128-Bit Hash, sprich dies sind über 10^38 Möglichkeiten.
Selbst wenn jmd. 1 Mrd. Rechner hat, die jede Sekunde 1 Mrd. Kombinationen testen würden, bräuchte er 10^20 Sekunden oder 10^13 (10 Billionen!) Jahre um alle Kombinationen auszuprobieren.
Ich weiß zwar nicht welche Fortschritte die Medizin in den nächsten Jahren macht, aber ich bezweifel stark nicht einmal meine Ur-Ur-Ur-Ur-Ur-Ur-Enkel dieses noch miterleben werden.
Aber es wird noch Unsinnger:
md5(mt_rand());
mt_rand() hat wie gesagt, einen Wertebereich von 0 bis 2,1 Mrd., demzufolge kann es auch nur 2,1 Mrd. Hashwerte geben.
Wenn ich also 1 Computer habe der 20 Mio. Werte pro Sekunde testet (ein doch schon sehr veralteter Wert) würde ich nicht einmal 2 Minuten brauchen, um alle Kombinationen durchzurechenn.
Selbst wenn du nun alle Zeichen verwendest (0-9, a-z, A-Z), hast du weiterhin nur diese 2,1 Mrd. Kombinationen wenn du mt_rand() als Ausgangswert verwendest.
Selbst das mehrmahlige Anwenden von mt_rand() bringt dich nicht
weiter.
Dieser Zufallsgenerator basiert auf einem Algorithmus der einen Startwert erhählt und ausgehend davon Zufallszahlen generiert.
Dieser Startwert ist allerdings eine uint-Variable und somit gibt es maximal nur 2^32 (oder 4 Mrd.) Kombinationen.
Du kannst also soviele Zeichen wie du willst verwenden und einen solangen 'Zufallsstring' erzeugen wie du willst, es gibt nuneinmal maximal nur 4 Mrd. Kombinationen.
Deine 62^32 ist also absolut überflüssig, du bleibst bei 4 Mrd. Kombinationen, egal was du anstellst.
Abhilfe schaffen hier kryptographisch sichere Zufallsgeneratoren, leider lassen sich diese nur sehr schlecht unter PHP initialisieren.
Das Beste ist es also, wenn du Leserechte auf /dev/urandom hast, so bekommst sehr gute Zufallszahlen.
Hat man solche Rechte nicht, wird es recht schwer mittels PHP an gute Zufallszahlen zu kommen.
Man sollte einen Hash von möglich vielen variablen Werten erstellen, u.A. mircotime, memory_get_usage, memory_get_peak_usage, getmypid und vielleicht Informationen über den User wie z.B. IP, Herkunft, Browser-Kennung (User-Agent) etc.
Wobei sich die Frage stellt, ob du wirklich soviele Kombinationen brauchst, denn oftmals sind 2, bzw. 4 Mrd. Werte ausreichend.
MFG
Vielen Dank, dass du mich für dieses Thema sensibilisiert hast.
mt_rand() erzeugt also 2,1 Mrd verschiedene Zahlen. Und die uint-Variable hat einen Wertebereich von 0-2^32. Ist das die maximale Größe eines Integer in PHP? Wobei sich mir dann die Frage stellt, wie man größere Zahlen in PHP speichern kann, die man von /dev/urandom bekommt.
Grüße
crille
Hallo,
mt_rand() erzeugt also 2,1 Mrd verschiedene Zahlen.
jo, die Funktion mt_getrandmax() die größte Zahl die mt_rand() zurückliefern kann.
Und die uint-Variable hat einen Wertebereich von 0-2^32.
Die zuständige uint-Variable belegt 32 Bit, womit eben 2^32 mögliche Kombinationen und somit ^32 mögliche Zahlen entstehen.
die man von /dev/urandom bekommt.
Aus /dev/urandom liest du keine Zahlen aus sondern bytes.
Du liest daraus (z.B. per fgets) 16 Bytes aus, jedes Byte kann einen Wert zwischen 0 und 255 haben womit dann 256^16 bzw. 2^128 mögliche Kombinationen entstehen.
Das Problem an den Zufallsgeneratoren die PHP anbietet ist, dass man diese nur mit einem uint-Wert initialisieren kann, welcher eben nur 2^32 mögl. Kombinationen hat und woraus folgt, dass es nur 2^32 mögl. Zufallsreihen gibt.
Sichere Zufallsgeneratoren arbeiten anders, ISAAC verwendet z.B. ein 256 elementiges int-Array zur Initialiserung des Zufallsgenerator.
Somit gibt es theoretisch 2^8192 Anfangswerte (statt 2^32) und somit auch (theoretisch) 2^8192 mögliche Zufallsreichen.
Ein Problem ist immer die Initialisierung von Zufallsgeneratoren. Oft sieht man ja den Ansatz:
mt_srand((double)microtime()*1000000);
Dies führt dazu, dass es maximal 1 Mio. Startwerte gibt, dort bringt es auch nichts wenn man theoretisch 2^8192 mögliche Startwerte hätte.
Deswegen verwendet man für die Initialisierung, die i.d.R. nur ein einziges mal pro Systemstart geschieht, sehr viele verschiedene variable Werte, wie z.B. welche Prozesse laufen, wieviel Speicher diese verwenden, welche User seit wann angemeldet sind, wann das System gestartet ist etc.
Sonst könnte man unter Linux /dev/urandom auch mittels /dev/random initialisieren.
/dev/random basiert, je nach Betriebssystem, auf einen echten Hardware-Zufallsgenerator der z.B. die Umgebungsgeräusche mit einbezieht.
Der Nachteil an /dev/random ist, dass dieser nicht beliebig lange Zufallsreichen produzieren kann, zur Initialisierung von /dev/urandom reicht dies aber vollkommen aus.
Lange Rede, kurzer Sinn:
/dev/urandom liefert (normalerweise) sehr sehr gute Zufallszahlen und kein PHP Zufallsgenerator kommt annähernd daran.
MFG