Jnnbo: Zufallszahl

Moin,

ich erzeige mit

md5(uniqid());

eine Zufallszahl für meine Einträge, wenn ich komplett fertig bin, sind es gut 10.000 Einträge. Wie hoch ist die Gefahr, dass ich damit doppelte Zahlenwerte habe?

akzeptierte Antworten

  1. Moin!

    md5(uniqid());
    

    eine Zufallszahl für meine Einträge, wenn ich komplett fertig bin, sind es gut 10.000 Einträge. Wie hoch ist die Gefahr, dass ich damit doppelte Zahlenwerte habe?

    echo "<?php  echo md5(uniqid()); ?>" | php | lc -c
    

    ergibt 32.

    Ein Blick auf die Ausgabe ergibt: Hexadezimal.

    Ok. 15^32/10000 kann der Windows-Taschenrechner wohl nicht.

    echo "15^32/10000" | bc
    

    ergibt: 4314398832739891950041055679321289

    Wie Wahrscheinlichkeit liegt also bei 1/4314398832739891950041055679321289

    Jörg Reinholz

    1. Moin!

      ergibt: 4314398832739891950041055679321289

      Und jetzt erzähle ich, warum das nicht stimmt:

      echo "<?php  echo uniqid(); ?>" | php | wc -c
      

      Ergebnis: nur 13!

      Ein Blick auf die Ausgabe sagt: Hexadezimal. Taschenrechner:

      echo "15^13/10000" | bc
      

      Ergebnis: 194619506835

      Also nur: 1/194.619.506.835

      Das ist nicht so sehr brauchbar. Im Lotto wird nämlich auch dauernd gewonnen.

      Mithin macht es keinen Sinn die Ausgaben von uniqid() dirch md5 zu jagen. Wenn überhaupt, dann: md5( uniqid() . uniqid() . uniqid() )

      Aber auch das wäre dumm, denn dann machst Du aus einer hexadezimalen Zahl mit 39 Stellen eine mit 32 Stellen, schränkst die Volatilität also ein.

      Jörg Reinholz

      1. Hallo Jörg,

        Aber auch das wäre dumm, denn dann machst Du aus einer hexadezimalen Zahl mit 39 Stellen eine mit 32 Stellen, schränkst die Volatilität also ein.

        was sollte ich dann deiner Meinung nach nehmen, dass ich eine "sichere" und einmalige Zahl habe, die man nicht so einfach erraten kann?

        1. Moin!

          was sollte ich dann deiner Meinung nach nehmen, dass ich eine "sichere" und einmalige Zahl habe, die man nicht so einfach erraten kann?

          Tja. Wie wäre es, wenn Du schon

          $zufall = uniqid() . uniqid() . uniqid();
          

          nimmst, auf das md5() drumrum einfach zu verzichten - statt die Rechenleistung kontraproduktiv zu "missnutzen"?

          Jörg Reinholz

          1. Hallo Jörg,

            Tja. Wie wäre es, wenn Du schon

            $zufall = uniqid() . uniqid() . uniqid();
            

            damit bekomme ich dann also so eine lange Zahl: 5526c7bd5371e5526c7bd537295526c7bd5375f Ok, nehme ich!

            1. Moin!

              $zufall = uniqid() . uniqid() . uniqid();
              

              damit bekomme ich dann also so eine lange Zahl: 5526c7bd5371e5526c7bd537295526c7bd5375f Ok, nehme ich!

              Naja, wenn da nicht noch was wäre:

              5526c7bd5371e
              5526c7bd53729
              5526c7bd5375f
              

              Diese "Zufallszahlen" unterscheiden sich viel zu wenig: nämlich, auf Grund des kurzen Zeitablaufes, nur in den letzten beiden Stellen.

              Wenn es nur eindeutig sein soll, dann nimm nur uniqueid().

              Wenn es "hinreichend wahrscheinlich eindeutig" und nicht zu erraten sein soll, dann nimm etwas wie:

              sha1(mt_rand(0,mt_getrandmax()) .uniqid() . uniqid() . uniqid());
              

              Aber Gnade Dir auf Windows-Systemen: da liefert mt_getrandmax() nämlich nur 2^15, also rund 32000

              Hast Du aber PHP >= 5.3, dann nimm einfach:

              $hex=bin2hex(openssl_random_pseudo_bytes(32));
              

              Jörg Reinholz

              1. Moin!

                Genau genommen willst Du scheinbar etwas, was eindeutig ist, und zugleich etwas, was schwer zu erraten ist. Das kann man sich aus etwas (was eindeutig ist) und etwas (was schwer zu erraten ist) zusammenbauen:

                Beispiel:

                $hex = uniqid() . bin2hex(openssl_random_pseudo_bytes(32));
                

                Jörg Reinholz

                1. Moin!

                  Moin!

                  Genau genommen willst Du scheinbar etwas, was eindeutig ist, und zugleich etwas, was schwer zu erraten ist. Das kann man sich aus etwas (was eindeutig ist) und etwas (was schwer zu erraten ist) zusammenbauen:

                  Beispiel:

                  $hex = uniqid() . bin2hex(openssl_random_pseudo_bytes(32));
                  

                  uniqid() ist aber nicht eindeutig! Ich habe Code in meiner Software, die aufgrund von Nicht-Eindeutigkeit von uniqid() noch einen Counter dranhängt, das wievielte Mal das jetzt ist.

                  Wenn du nicht in der Lage bist, 32 zufällige Bytes als ausreichend zufällig zu akzeptieren, dann erhöhe den Wert. Uniqid() liefert 13 Hexzahlen, also 6,5 Bytes. Aufgerundet wären das statt 32 also 39 Zufallsbytes, und das ist sogar extrem besser als uniqid(), weil dort die meisten Zahlen konstant sind.

                  Grüße Sven

                  1. Moin!

                    uniqid() ist aber nicht eindeutig! Ich habe Code in meiner Software, die aufgrund von Nicht-Eindeutigkeit von uniqid ()

                    Beschreibung von php.net: uniqueid() ... "Gibt eine eindeutige ID mit Präfix zurück, die auf der aktuellen Zeit in Mikrosekunden basiert."

                    Könntest Du bitte auf die, sehr wahrscheinlich vom Problem des TO doch recht ordentlich abweichenden Umstände eingehen, unter denen es Dir gelungen ist, mit unique_id() nicht unique ids zu erzeugen?

                    13 Stellen hex sind 6,5 Bbyte sind 54 bit, sind also 2^54 Millisekunden. Wiederholung ergo frühestens nach

                    • 18014398509481984 Millisekunden
                    • 18014398509481 Sekunden
                    • 300239975158 Minuten
                    • 5003999585 Stunden
                    • 208499982 Tagen
                    • 570800 Jahren
                    • 142710 Rechnergenerationen (a 4 Jahre)
                    • 22833 mesnchl. Generationen (a 25 Jahre)

                    Du müsstest ergo mit passender Software auf einem Mehrprozessorsystem die ids erzeugt haben oder auf sehr vielen Rechnern uniqueid() gestartet haben, wodurch es zu dem Umstand kam, dass die Uhrzeit jeweils bis auf die Millisekunde stimmte. Nicht ganz undenkbar.

                    Oder lief da was unter Windows? Kann das real microtime()?

                    Jörg Reinholz

                    1. Moin!

                      • 18014398509481984 Millisekunden
                      • 18014398509481 Sekunden
                      • 300239975158 Minuten
                      • 5003999585 Stunden
                      • 208499982 Tagen
                      • 570800 Jahren
                      • 142710 Rechnergenerationen (a 4 Jahre)
                      • 22833 mesnchl. Generationen (a 25 Jahre)

                      Falls Du es nicht glaubst:

                      root@lvps92-51-***.***:~# echo "<?php echo uniqid(); ?>" | php
                      

                      5526fd583a759

                      Fast gleichzeitig:

                      trainer:~$ echo "<?php echo uniqid(); ?>" | php
                      

                      5526fd531879d

                      Jörg Reinholz

                    2. Moin!

                      uniqid() ist aber nicht eindeutig! Ich habe Code in meiner Software, die aufgrund von Nicht-Eindeutigkeit von uniqid ()

                      Beschreibung von php.net: uniqueid() ... "Gibt eine eindeutige ID mit Präfix zurück, die auf der aktuellen Zeit in Mikrosekunden basiert."

                      Könntest Du bitte auf die, sehr wahrscheinlich vom Problem des TO doch recht ordentlich abweichenden Umstände eingehen, unter denen es Dir gelungen ist, mit unique_id() nicht unique ids zu erzeugen?

                      Unittests haben unregelmäßig Fehler angezeigt, deren Analyse ergeben hat, dass dieselbe uniqid() verwendet wurde, die schon einmal erzeugt worden war. Das Abfangen dieser speziellen Situation hat das Problem behoben.

                      Ach ja: Möglicherweise waren zwei Server parallel am Werk - warum die aber auf die Mikrosekunde identisch uniqid() aufgerufen bekommen haben sollen bei Requests, die mehrere Sekunden auseinanderliegen, ist nicht nachvollziehbar - es ist aber aufgrund der Entstehungsmethode von uniqid() jedenfalls nicht garantiert, dass es nicht zu Wiederholungen kommt. Wenn beispielsweise der ntpd im Hintergrund an der Uhr dreht, kommt eventuell dieselbe Uhrzeit zweimal. Servercluster, Mehrkernsysteme und virtualisierte Umgebungen (Cloud etc.) sind ja außerdem nichts ungewöhnliches.

                      13 Stellen hex sind 6,5 Bbyte sind 54 bit, sind also 2^54 Millisekunden. Wiederholung ergo frühestens nach

                      • 18014398509481984 Millisekunden
                      • 18014398509481 Sekunden
                      • 300239975158 Minuten
                      • 5003999585 Stunden
                      • 208499982 Tagen
                      • 570800 Jahren
                      • 142710 Rechnergenerationen (a 4 Jahre)
                      • 22833 mesnchl. Generationen (a 25 Jahre)

                      Du müsstest ergo mit passender Software auf einem Mehrprozessorsystem die ids erzeugt haben oder auf sehr vielen Rechnern uniqueid() gestartet haben, wodurch es zu dem Umstand kam, dass die Uhrzeit jeweils bis auf die Millisekunde stimmte. Nicht ganz undenkbar.

                      Es reicht, dass das undenkbare real passiert ist, und zwar so regelmäßig, dass nicht nur irgendein Testlauf unerwartet gescheitert ist, sondern nachprüfbar so häufig, dass es genervt hat.

                      Der Code für die uniqid() ist übrigens der hier: https://github.com/php/php-src/blob/master/ext/standard/uniqid.c#L72-L83

                      Acht Hexzahlen aus den Sekunden plus fünf Hexzahlen aus den Mikrosekunden, die zuvor modulo 0x100000 genommen wurden (was nichts ändert - Mikrosekunden werden nie größer als eine Million).

                      Grüße Sven

                      1. Moin!

                        Wenn beispielsweise der ntpd im Hintergrund an der Uhr dreht, kommt eventuell dieselbe Uhrzeit zweimal.

                        Das sollte eigentlich nicht passieren. Zumindest glaube ich gelesen zu haben, dass die Systemzeit dann nicht etwa hart verstellt wird, sondern dass die Differenz in mehreren Schritten angeglichen wird und es also keine zwei Zeitpunkte gibt, an welchen die gleiche Systemzeit zurück geliefert wird. Prinzipiell kann Linux sogar Nanosekunden zurückgeben

                        ~> date +%s.%N
                        1428658410.775922668
                        

                        also ist diese schrittweise Verstellung auch im Microsekunden-Bereich machbar.

                        Stellt sich die Frage, was Windows kann. In dem von Dir verlinkten Quelltext zur Funktion uniqid() glaube ich Hinweise gefunden zu haben, dass es zumindest auf 32-Bit-Windows-Systemen und auch mit cygwin.dll wohl das eine oder kleinere Problem bei derart feinen Zeitauflösungen gibt.

                        Was jetzt den Unit-Test bestrifft: Da braucht es unter Umständen nur ein Mehrprozessor-System und die entsprechende Anzahl von parallelen Threads. So könnte, genug Lotto vorausgesetzt durchaus so ein Konflikt in einem Unit-Test provozierbar sein, während er im Alltag nahezu ausgeschlossen ist.

                        In einem Punkt hast Du allerdings durchaus recht, denn der TO will was Blaues und was Rotes. Lila klingt nur so als wäre es das.

                        Das Blaue: Wenn ich eine Identifizierung brauche, dann sollte, genau wie Du trefflich vorschlägst, und wenn die Datenbank schon benutzt wird, deren Möglichkeit, eine (schlicht und einfach fortlaufende) ID zu generieren, auch genutzt werden. (Punkt!)

                        Das Rote: Wenn ein nicht erratbares Muster (String, Zahl) quasi als Passwort gewünscht wird, dann kann man das durch Zufall erzeugen (und hier ist ETWAS wie bin2hex(openssl_random_pseudo_bytes(32)) gewiss nicht die schlechteste Lösung, weil ja wohl kaum jemand etwas griffiges gegen openssl einzuwenden hat)

                        Am Ende der Story muss man das nur noch verbinden und, darum geht es hier wohl, die Daten nur ausliefern, wenn ID und "Passwort" stimmen.

                        Jörg Reinholz

                        1. Hallo Jörg,

                          Das Blaue: Wenn ich eine Identifizierung brauche, dann sollte, genau wie Du trefflich vorschlägst, und wenn die Datenbank schon benutzt wird, deren Möglichkeit, eine (schlicht und einfach fortlaufende) ID zu generieren, auch genutzt werden. (Punkt!)

                          Das Rote: Wenn ein nicht erratbares Muster (String, Zahl) quasi als Passwort gewünscht wird, dann kann man das durch Zufall erzeugen (und hier ist ETWAS wie bin2hex(openssl_random_pseudo_bytes(32)) gewiss nicht die schlechteste Lösung, weil ja wohl kaum jemand etwas griffiges gegen openssl einzuwenden hat)

                          da ich noch nicht upvoten darf, hier als kleiner Kommentar: Sehe ich genauso. Daumen hoch

                          Gruß, Dennis

                          1. da ich noch nicht upvoten darf, hier als kleiner Kommentar: Sehe ich genauso. Daumen hoch

                            Wer auch immer mir den "Daumen hoch" gegeben hat: Danke. Jetzt darf ich auch upvoten :-)

                            Gruß, Dennis

          2. Moin!

            Moin!

            was sollte ich dann deiner Meinung nach nehmen, dass ich eine "sichere" und einmalige Zahl habe, die man nicht so einfach erraten kann?

            Tja. Wie wäre es, wenn Du schon

            $zufall = uniqid() . uniqid() . uniqid();
            

            nimmst, auf das md5() drumrum einfach zu verzichten - statt die Rechenleistung kontraproduktiv zu "missnutzen"?

            Reden wir von Zufallszahlen? Dann ist uniqid() so ziemlich das falscheste, was man nehmen kann, denn da gehen nur Parameter in die Bildung mit ein, die man kennen bzw, raten kann.

            Siehe Handbuch: http://php.net/uniqid

            Zitate:

            Warning This function does not create random nor unpredictable strings. This function must not be used for security purposes. Use a cryptographically secure random function/generator and cryptographically secure hash functions to create unpredictable secure IDs.

            Caution This function 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().

            Grundsätzlich kann man sagen, dass uniqid() mit dem Fortschritt der Zeit aufsteigende IDs erzeugt, weil die aktuelle Systemzeit in die Bildung der ID mit einfließt. Wie gut man Microtime erraten kann, kann man sich denken: Einfach auf die Uhr gucken verrät den größten Teil, unsicher sind allenfalls die Sekunden und Millisekunden.

            Es hilft auch nichts, das Ergebnis von uniqid() in md5() reinzustecken, denn der Wertebereich von uniqid ist begrenzt: Es werden standardmäßig Strings von 13 Zeichen Länge aus dem Hexzahlenbereich 0-9A-F erzeugt. md5() ändert an diesem begrenzten Wertebereich nichts, d.h. es entstehen maximal soviele verschiedene MD5-Hashes, wie es 13-stellige Hexzahlen gibt - die restlichen mit MD5 erzeugbaren Werte werden nie produziert.

            Kommen wir also zurück auf die Ausgangsfrage: Datenbank und Autoinkrement gefallen nicht, es soll etwas sein, was so eindeutig ist wie Autoinkrement, aber weniger einfach zu erraten.

            Wenn man etwas nicht erraten soll, braucht man starken, kryptografischen Zufall. Und wenn etwas eindeutig sein soll, und man das sicherzustellen hat, braucht man eine Datenbank mit UNIQUE-Spalte, in die man den Zufallswert reinschreibt und dabei evtl. merkt, dass man den schon früher erzeugt hatte und einen neuen Wert ermitteln muß.

            Wie man in PHP bestmöglich je nach Systemfähigkeiten Zufallsquellen anzapft, sieht man hier:

            https://github.com/ircmaxell/password_compat/blob/6147131320e930186a37bc942ae067636302cf1c/lib/password.php#L102-L137

            Das Schreiben des ermittelten Wertes in eine DB-Spalte mit UNIQUE-Index muss ich vermutlich nicht genauer ausführen.

            Grüße Sven

            1. Moin!

              Hihi. Um 21:41 waren wir ein gutes Stück weiter.

              Jörg Reinholz

              1. Moin!

                Hihi. Um 21:41 waren wir ein gutes Stück weiter.

                20:41 bzw 21:07 - und ich hatte nicht den Eindruck, dass du von der Nutzung von uniqid() abgerückt bist.

                Grüße Sven

                1. Moin!

                  20:41 bzw 21:07 - und ich hatte nicht den Eindruck, dass du von der Nutzung von uniqid() abgerückt bist.

                  Die derzeit als brauchbar angesehene Lösung verzichtet auch nicht darauf.

                  Jörg Reinholz

                  1. Moin!

                    Moin!

                    20:41 bzw 21:07 - und ich hatte nicht den Eindruck, dass du von der Nutzung von uniqid() abgerückt bist.

                    Die derzeit als brauchbar angesehene Lösung verzichtet auch nicht darauf.

                    Wer sieht die als brauchbar an?

                    Grüße Sven

      2. Liebe Mitdenker, liebe Wissende, liebe Neugierige,

        ja!

        Und jetzt erzähle ich, warum das nicht stimmt:

        Ergebnis: 194619506835

        Also nur: 1/194.619.506.835

        Das ist nicht so sehr brauchbar. Im Lotto wird nämlich auch dauernd gewonnen.

        Mithin macht es keinen Sinn die Ausgaben von uniqid() dirch md5 zu jagen. Wenn überhaupt, dann: md5( uniqid() . uniqid() . uniqid() )

        Uniqid('', true) sollte man immer ohne md5() benutzen, damit keine Doubletten entstehen können. Md5() könnte durchaus mal für zwei unterschiedliche Argumentwerte dasselbe Ergebnis liefern. Uniqid("", true) wird aber, wenn man es nicht direkt in aufeinanderfolgenden Statements benutzt, keine Doubletten liefern.

        Aber auch das wäre dumm, denn dann machst Du aus einer hexadezimalen Zahl mit 39 Stellen eine mit 32 Stellen, schränkst die Volatilität also ein.

        Spirituelle Grüße
        Euer Robert
        robert.r@online.de

        --
        Möge der wahre Forumsgeist ewig leben!
      3. Hallo

        Ergebnis: 194619506835

        Also nur: 1/194.619.506.835

        Das ist nicht so sehr brauchbar. Im Lotto wird nämlich auch dauernd gewonnen.

        Beim Lotto beträgt die Wahrscheinlichkeit (inkl. Superzahl) zirka 1/144 Mio.. Das ist gegenüber deinem Ergebnis mithin eine mehr als tausendfach höhere Wahrscheinlichkeit. Und dennoch gewinnen immer nur „die Anderen“. ;-)

        Tschö, Auge

        --
        Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war. Terry Pratchett, “Wachen! Wachen!
    2. Hallo Jörg,

      Ok. 15^32/10000 kann der Windows-Taschenrechner wohl nicht.

      echo "15^32/10000" | bc
      

      ergibt: 4314398832739891950041055679321289

      Wie Wahrscheinlichkeit liegt also bei 1/4314398832739891950041055679321289

      ok, damit kann ich leben, dann bin ich also auf dem richtigen Weg. Ich könnte natürlich auch mit der ID arbeiten, die von der Datenbank selber vergeben wird, ist mir aber zu unsicher, vor allem kann man die ID ohne Probleme erraten, so eine lange Zahl eher nicht.

  2. Liebe Mitdenker, liebe Wissende, liebe Neugierige,

    ja!

    ich erzeige mit

    md5(uniqid());
    

    eine Zufallszahl

    das ist keine echte Zufallszahl. Siehe Handbuch

    Wenn der Wertebereich für die Zeit zuende ist, ist der Nummernkreis für die Unique-ID ausgeschöpft

    für meine Einträge, wenn ich komplett fertig bin, sind es gut 10.000 Einträge. Wie hoch ist die Gefahr, dass ich damit doppelte Zahlenwerte habe?

    Spirituelle Grüße
    Euer Robert
    robert.r@online.de

    --
    Möge der wahre Forumsgeist ewig leben!
  3. Hallo Jnnbo

    ich erzeige mit

    md5(uniqid());
    

    eine Zufallszahl für meine Einträge, wenn ich komplett fertig bin, sind es gut 10.000 Einträge. Wie hoch ist die Gefahr, dass ich damit doppelte Zahlenwerte habe?

    dass uniqid() keine Zufallszahlen generiert, hat Sven ja schon beschrieben. uniqid() macht wirklich nicht viel anderes, als eine Zeiteinheit, in (Dezimal-) Mikrosekunden gerechnet, in ein anderes Zahlensystem, hier das Hexadezimalsystem, zu überführen. Du kannst also (fast) beliebig damit hin-und-her rechnen. Dass das so ist, kannst Du auch schon am Quellcode sehen. Oder mal selbst Funktionen wie base_convert() oder ähnliches ausprobieren. Andere haben sich da schon mit beschäftigt.

    Auch dass MD5 daran nichts wirklich ändert oder die Sache im ungünstigsten Fall sogar verschlechtert, hat Jörg schon angesprochen. Sollte MD5 in dieser Hinsicht funktionieren, was es offensichtlich tut, wirst Du für denselben Input immer das gleiche Ergebnis erhalten.

    Was Du machst ist also wohl Security through obscurity oder Obfuskation. Das ist im Normalfall ein nettes Gimmick, mehr nicht. Daran kannst Du auch durch die mehrfache Anwendung von uniqid() nichts ändern. Du könntest mit ähnlichem Ergebnis auch die Cäsar-Verschlüsselung (in PHP z.B. str_rot13() o.ä.) verwenden. Irgendwo hier im Forum gab's in letzter Zeit auch noch einen Beitrag zu base64_encode() (finde ich gerade leider nicht, ändert aber auch nichts daran, dass das nichts mit Zufall zu tun hat, auch wenn es auf den ersten Blick so aussehen könnte).

    Aber jetzt wieder zurück zu Deiner Frage:

    Wie hoch ist die Gefahr, dass ich damit doppelte Zahlenwerte habe?

    Wenn uniqid() so funktioniert, wie es gedacht ist: Gleich null.

    Ansonsten: Nahezu null. Denn würde uniqid() Zufallszahlen generieren und wären diese absolut gleichverteilt, kannst Du Dir die Wahrscheinlichkeit mit Hilfe der Laplace-Formel ausrechnen. Ansonsten wird es etwas komplizierter, das Ergebnis dürfte aber in etwa das Gleiche sein. Auch wenn das häufig völlig an der eigenen Intuition verbeigeht, siehe z.B. das Geburtstagsparadoxon (welches ziemlich genau das beschreibt).

    Gruß, Dennis

    1. Lieber Dennis, liebe Mitdenker, liebe Wissende, liebe Neugierige,

      ja!

      Das ist ja nett, dass Du nochmal versucht hast, alles zusammenzufassen. Warum Du aber scheinbar mein Posting von 20:07 übersehen hast, in dem ich bereits darauf hinwies, dass man mit uniqid() -> Handbuch keine echten Zufallszahlen erzeugen kann, weiß ich noch nicht.

      Viel wichtiger ist aber, dass Ihr hier alle immer noch meinen Hinweis auf die **Nicht-**Einmaligkeit der Zeichenfolgen im Posting von 20:38 missachtet.

      Kleines Testskript zum Ausprobieren:

      <?php  ### unique_id.php ### Funktion uniqid() testen ### utf-8 
      
          header('Content-Type: text/html; CharSet=utf-8;');
      
          $_uniqueid = array();
          for ( $i = 0; $i < 5; $i++)
          {
      	$_uniqueid[] = uniqid();
          }
      		
          echo "<pre>\r\n";
          echo htmlspecialchars(print_r($_uniqueid, 1));
          echo "</pre>\r\n";
      
      ?>
      

      Ich bekam da als Ausgabe:

      Array
      (
          [0] => 55278b89c9817
          [1] => 55278b89c9817
          [2] => 55278b89c9817
          [3] => 55278b89c9817
          [4] => 55278b89c9817
      )
      

      Warum ich die IDs erst in ein Array geschrieben habe? Weil die Ausgabe auf die Standardausgabe Zeit kostet und die wollte ich hier zwischen den Aufrufen der Funktion bewusst kurz halten!

      Nun schauen wir uns das Ganze nochmal mit uniqid('', true) an:

      Array
      (
          [0] => 55278e43f3830
          [1] => 55278e43f3830
          [2] => 55278e43f3830
          [3] => 55278e43f3830
          [4] => 55278e43f3830
          [5] => 55278e43f38307.48271792
          [6] => 55278e43f38302.27676127
          [7] => 55278e43f38302.30131205
          [8] => 55278e43f38306.61604230
          [9] => 55278e43f38305.26805643
      )
      

      Von 0 bis 5 mit uniqid() und von 5 bis 9 mit uniqid('', true);

      Mit der von mir vorgeschlagenen Verwendung von uniqid('', true) ist also die Einmaligkeit der Zeichenfolge (auf meinem Rechner) gewährleistet.

      Will man nun noch die Erratbarkeit verschlechtern, müsste man z.B. noch einen String mit mt_rand() -> Handbuch voranstellen (oder anhängen).

      <?php  ### unique_id.php ### Funktion uniqid() testen ### utf-8 ### ÄÖÜäöü
      
          header('Content-Type: text/html; CharSet=utf-8;');
      
          $_uniqueid = array();
          for ( $i = 0; $i < 5; $i++)
          {
      	$_uniqueid[] = uniqid();
          }
      	
          for ( $i = 0; $i < 5; $i++)
          {
      	$_uniqueid[] = uniqid('', true);
          }
      	
          for ( $i = 0; $i < 5; $i++)
          {
      	$_uniqueid[] = uniqid(mt_rand(1,99999), true);
          }
      	
          echo "<pre>\r\n";
          echo htmlspecialchars(print_r($_uniqueid, 1));
          echo "</pre>\r\n";
      
      ?>
      
      Array
      (
          [0] => 55278fb97caca
          [1] => 55278fb97caca
          [2] => 55278fb97caca
          [3] => 55278fb97caca
          [4] => 55278fb97caca
          [5] => 55278fb97caca1.12090844
          [6] => 55278fb97caca7.90725032
          [7] => 55278fb97caca8.19101436
          [8] => 55278fb97caca0.45335224
          [9] => 55278fb97caca3.08279841
          [10] => 6739155278fb97caca5.93560867
          [11] => 4116255278fb97caca5.86801685
          [12] => 6838855278fb97caca9.39616501
          [13] => 4891355278fb97caca3.30257003
          [14] => 486055278fb97caca4.84110264
      )
      

      Wie man in den Elementen 10 bis 14 unschwer erkennen kann, wird der String damit schwer erratbar und ist grantiert eineindeutig, solange es nur eine erzeugende Instanz gibt. Außerdem sieht man, dass bereits die kleine Zusatzaufgabe (mt_rand()) schon für eine neue Zeichenfolge im Stamm der von uniqid() erzeugten Zeichenkette sorgen kann.

      Wenn man also nicht mit einem Uniqe-Index auf eine DBMS-Tabelle arbeiten kann, oder auch für das Anlegen von Dateien im Dateisystem nicht die Option 'x' benutzt (warum auch immer), und mit einem äußerst geringen restrisiko leben kann, dann ist das mMn die einzige Möglichkeit, die Anforderungen des OP zu erfüllen.

      Spirituelle Grüße
      Euer Robert
      robert.r@online.de

      --
      Möge der wahre Forumsgeist ewig leben!
      1. Liebe Mitdenker, liebe Wissende, liebe Neugierige,

        ja!

        Jetzt fange ich schon genauso an, wie Fastix ;-)

        Kleines modifiziertes Testskript zum Ausprobieren:

        <?php  ### unique_id.php ### Funktion uniqid() testen ### utf-8 
        
            header('Content-Type: text/html; CharSet=utf-8;');
            
            $_uniqueid = array();
            for ( $i = 0; $i < 5; $i++)
            {
                usleep(1);
        	$_uniqueid[] = uniqid();
            }
        		
            echo "<pre>\r\n";
            echo htmlspecialchars(print_r($_uniqueid, 1));
            echo "</pre>\r\n";
        
        ?>
        

        Die Microsekunde muss übrig sein! In Wirklichkeit wird die Wartezeit sogar etwas größer werden, da usleep() die Prozesskontrolle kurz zurück gibt und damit andere Prozesse zwischendurch angefangen werden.

        Spirituelle Grüße
        Euer Robert
        robert.r@online.de

        --
        Möge der wahre Forumsgeist ewig leben!
        1. Moin!

          Jetzt fange ich schon genauso an, wie Fastix ;-)

          Na und? Ich sehe nichts schlechtes darin

          • sich selbst zu korrigieren und zu verbessern
          • eventuelle Missverständnisse selbst aufzuklären
          • später vorausgesehene Probleme und deren Lösung zu zeigen

          Jetzt kann man ja seine eigenen Beiträge (oft) noch ändern…

          Jörg Reinholz

          1. Liebe Mitdenker, liebe Wissende, liebe Neugierige,

            ja!

            Moin!

            Jetzt fange ich schon genauso an, wie Fastix ;-)

            Na und? Ich sehe nichts schlechtes darin

            • sich selbst zu korrigieren und zu verbessern
            • eventuelle Missverständnisse selbst aufzuklären
            • später vorausgesehene Probleme und deren Lösung zu zeigen

            Jetzt kann man ja seine eigenen Beiträge (oft) noch ändern…

            Ist ja auch besser, als das Denken einzustellen :-)
            Ich musste trotzdem grinsen...

            Spirituelle Grüße
            Euer Robert
            robert.r@online.de

            --
            Möge der wahre Forumsgeist ewig leben!
      2. Hallo Robert,

        Das ist ja nett, dass Du nochmal versucht hast, alles zusammenzufassen. Warum Du aber scheinbar mein Posting von 20:07 übersehen hast, in dem ich bereits darauf hinwies, dass man mit uniqid() -> Handbuch keine echten Zufallszahlen erzeugen kann, weiß ich noch nicht.

        da das eigentlich keine Zusammenfassung sein sollte, sondern eine kleine Ergänzung, habe ich auch nichts vergessen. Dass z.B. auch Sven zwischenzeitlich in den Quellcode geguckt hat, wusste ich noch nicht, als ich den Beitrag geschrieben habe.

        Hätte ich eine Zusammenfassung schreiben wollen, hätte ich uniqid() hat absolut gar nichts mit Zufallzahlen zu tun geschrieben.

        Viel wichtiger ist aber, dass Ihr hier alle immer noch meinen Hinweis auf die **Nicht-**Einmaligkeit der Zeichenfolgen im Posting von 20:38 missachtet.

        Das hat nichts mit Missachtung zu tun. uniqid() macht genau das, was es soll. Nämlich mehr oder weniger Mikrosekunden aus dem Dezimal- ins Hexidezimalsystem zu überführen. Und in seinem Rahmen (zwei aufeinander folgende Aufrufe > 1 Mikrosekunde, keine konkurrierenden/parallelen Prozesse, absolut proportionale Systemzeit, also z.B. kein Umstellen der Systemzeit) ist dies absolut eindeutig. Dazu muss man aber nun mal wissen, was da im Hintergrund passiert.

        Kleines Testskript zum Ausprobieren:

        Das ist alles richtig. Es ändert aber nichts daran, dass Du mit uniqid keinen echten Zufall erzeugen kannst. Du verwendest ja beispielsweise mt_rand(), das erweist seinen Dienst auch ganz ohne uniqid().

        Und wenn es Dir nur um die Eindeutigkeit geht, kannst Du auch einfach ein usleep() oder so davor setzen. Oder noch besser eine while()-Schleife drum herum basteln, die prüft, ob die Zahl schon existiert und das Statement sonst gegebenenfalls nochmals ausführt.

        Gruß, Dennis