2008-09-10 10 views
12

Ich suche nach einer Möglichkeit, speziell in PHP, dass ich garantiert immer einen eindeutigen Schlüssel bekomme.Eindeutige Schlüsselgenerierung

Ich habe getan, die folgenden:

strtolower(substr(crypt(time()), 0, 7)); 

Aber ich gefunden habe, dass einmal in eine Weile ich mit einem doppelten Schlüssel am Ende (selten, aber oft genug).

habe ich auch tun dachte:

strtolower(substr(crypt(uniqid(rand(), true)), 0, 7)); 

Aber nach der PHP-Website, uniqid() könnte, wenn uniqid() zweimal in der gleichen Mikro genannt wird, könnte es den gleichen Schlüssel erzeugen. Ich denke, dass der Zusatz von rand() es selten, aber immer noch möglich wäre.

Nach den oben genannten Zeilen bin ich auch Zeichen wie L und O entfernen, so dass es für den Benutzer weniger verwirrend ist. Dies ist vielleicht ein Teil der Ursache für die Duplikate, aber immer noch notwendig.

Eine Option, an die ich denke, ist die Erstellung einer Website, die den Schlüssel generiert und ihn in einer Datenbank speichert, um sicherzustellen, dass er vollständig einzigartig ist.

Irgendwelche anderen Gedanken? Gibt es da draußen irgendwelche Webseiten, die eine API haben oder einfach den Schlüssel zurückgeben? Ich habe http://userident.com gefunden, aber ich bin mir nicht sicher, ob die Schlüssel vollständig eindeutig sein werden.

Dies muss im Hintergrund ohne Benutzereingaben ausgeführt werden.

+0

Warum müssen die Kennwörter vollständig eindeutig sein? –

+0

Ich nehme an, Krypt ist nur, weil Sie Wert kryptieren müssen, es hat nichts damit zu tun, einzigartigen Wert zu schaffen, nicht wahr ?! –

+0

Siehe auch: [PHP-Funktion zum Generieren von v4 UUID] (http://StackOverflow.com/a/15875555/1338292). –

Antwort

19

Es gibt nur 3 Möglichkeiten, eindeutige Werte zu generieren, eher sie Passwörter, Benutzer-IDs, etc .:

  1. Verwenden Sie einen wirksamer GUID-Generator - das ist lang und nicht geschrumpft werden kann. Wenn Sie nur Teil verwenden, erhalten Sie FAIL.
  2. Mindestens ein Teil der Nummer wird sequenziell aus einer einzelnen Sequenz generiert. Sie können Fluff oder Encoding hinzufügen, damit es weniger sequenziell aussieht. Vorteil ist, sie beginnen kurz - Nachteil ist, dass sie eine einzige Quelle benötigen. Die Umgehung für die Einzelquellenbegrenzung besteht darin, nummerierte Quellen zu haben, so dass Sie die [Quell-Nr.] + [SEQ-Nr.] Einschließen und dann jede Quelle ihre eigene Sequenz erzeugen kann.
  3. Generieren Sie sie auf andere Weise und überprüfen Sie sie dann mit der einzelnen Historie der zuvor generierten Werte.

Jede andere Methode ist nicht garantiert. Denken Sie daran, dass Sie im Grunde eine Binärzahl generieren (es ist ein Computer), aber dann können Sie es in Hexadezimal, Dezimal, Base64 oder eine Wortliste codieren. Wählen Sie eine Kodierung, die zu Ihrer Verwendung passt. In der Regel für Benutzer eingegebenen Daten möchten Sie eine Variation von Base32 (die Sie angedeutet).

Hinweis zu GUIDs: Sie erhalten ihre Stärke der Einzigartigkeit von ihrer Länge und der Methode, um sie zu generieren. Alles weniger als 128-Bit ist nicht sicher. Neben der Generierung von Zufallszahlen gibt es Eigenschaften, die in eine GUID übernommen werden, um sie eindeutiger zu machen. Beachten Sie, dass sie nur praktisch einzigartig sind, nicht völlig einzigartig. Es ist möglich, obwohl praktisch unmöglich, ein Duplikat zu haben.

Aktualisierter Hinweis zu GUIDs: Seit ich das geschrieben habe, habe ich gelernt, dass viele GUID-Generatoren einen kryptografisch sicheren Zufallsgenerator verwenden (schwierig oder unmöglich, die nächste generierte Zahl vorherzusagen und wahrscheinlich nicht zu wiederholen). Es gibt tatsächlich 5 verschiedene UUID algorithms. Algorithmus 4 wird von Microsoft derzeit für die Windows-GUID-Generierungs-API verwendet. A GUID ist Microsofts Implementierung des UUID-Standards.

aktualisieren: Wenn Sie 7-16 Zeichen wollen, dann müssen Sie entweder Methode 2 oder 3.

Unterm Strich verwenden: Ehrlich gesagt ist es nicht so etwas wie einzigartig. Selbst wenn Sie mit einem sequentiellen Generator arbeiten würden, würde Ihnen der Speicher mit allen Atomen des Universums ausgehen und Sie würden sich immer wieder selbst wiederholen und wiederholen. Deine einzige Hoffnung wäre der Hitzetod des Universums, bevor du diesen Punkt erreicht hast.

Selbst der beste Zufallszahlengenerator hat die Möglichkeit, sich zu wiederholen, und zwar gleich der Gesamtgröße der Zufallszahl, die Sie erzeugen. Nehmen Sie ein Viertel zum Beispiel. Es ist ein völlig zufälliger Bit-Generator, und seine Chancen zu wiederholen sind 1 in 2.

So kommt es zu Ihrer Schwelle der Einzigartigkeit. Sie können 100% Eindeutigkeit in 8 Ziffern für 1.099.511.627.776 Zahlen haben, indem Sie eine Sequenz verwenden und dann base32 kodieren. Jede andere Methode, bei der nicht nach einer Liste vergangener Nummern gesucht wird, hat eine Quote von n/1.099.511.627.776 (wobei n = Anzahl der vorherigen erzeugten Zahlen) nicht eindeutig.

+0

Hallo, haben Sie weitere Informationen über Nummer 2, möchte ich diese Art der Code-Generierung mit verschiedenen "Quellen" verwenden, Danke. – Jon

+0

@Jon: Ich habe keine Lesung zu diesem Thema, aber im Wesentlichen verketten Sie den Quellbezeichner mit einer Sequenz aus dieser Quelle. Sie wissen also, dass es einzigartig ist. Zum Beispiel, wenn Sie zwei Quellen hätten, dann hätten Sie eine Folge von A1, A2, A3, A4 ... A999 und eine andere Sequenz von B1, B2, B3, B4. .. B999. Da eine ID von Quelle A niemals mit B beginnt, wissen Sie, dass es niemals zu einer Kollision kommen wird. –

+0

k danke, könnte der Quellenbezeichner eine ID für eine db-Tabelle sein, so dass Informationen, wenn ein Code eingegeben wird, aus einem Datensatz in einer Tabelle gesammelt werden können? – Jon

0

Ohne den Code zu schreiben, würde meine Logik:

eine zufällige Zeichenfolge generiert aus, was auch immer akzeptablen Zeichen, die Sie mögen.
Dann fügen Sie die Hälfte des Datumsstempels (teilweise Sekunden und alle) an der Vorderseite und die andere Hälfte bis zum Ende (oder irgendwo in der Mitte, wenn Sie bevorzugen).

Bleiben Sie JOLLY!

+1

Dies ist nahe, aber abhängig von Ihrer zufälligen Routine hat nur etwas über Mikrosekunde Genauigkeit. Wie er erwähnte, scheiterte Uniqid für die gleiche Möglichkeit. –

0

Wenn Sie Ihre ursprüngliche Methode verwenden, aber den Benutzernamen oder die E-Mail-Adresse vor dem Kennwort hinzufügen, wird es immer eindeutig sein, wenn jeder Benutzer nur ein Kennwort haben kann.

0

Sie könnten in diesem Artikel interessiert sein, die sich mit dem gleichen Problem beschäftigt: GUIDs are globally unique, but substrings of GUIDs aren't.

Das Ziel dieses Algorithmus ist die Kombination von Zeit und Ort („Raum-Zeit-Koordinaten“ für die Relativität geeks gibt) als Eindeutigkeitsschlüssel zu verwenden. Die Zeitmessung ist jedoch nicht perfekt, daher besteht die Möglichkeit, dass zum Beispiel zwei GUIDs in schneller Folge von derselben Maschine erzeugt werden, so nahe beieinander, dass der Zeitstempel derselbe ist. Das ist, wo die uniquifier kommt

0

Ich mache es in der Regel wie folgt aus:.

$this->password = ''; 

for($i=0; $i<10; $i++) 
{ 
    if($i%2 == 0) 
     $this->password .= chr(rand(65,90)); 
    if($i%3 == 0) 
     $this->password .= chr(rand(97,122)); 
    if($i%4 == 0) 
     $this->password .= chr(rand(48,57)); 
} 

Ich nehme an, es gibt einige theoretische Löcher, aber ich hatte noch nie ein Problem mit Duplikation. Ich benutze es normalerweise für temporäre Passwörter (wie nach einem Passwort-Reset) und es funktioniert gut genug dafür.

-1

Normalerweise mache ich einen zufälligen Teilstring (randomize wie viele Zeichen zwischen 8 und 32, oder weniger für die Benutzerfreundlichkeit) oder die MD5 von einem Wert, die ich bekommen habe, oder die Zeit oder eine Kombination. Für mehr Zufälligkeit mache ich MD5 von come Wert (zB Nachname) verketten, dass mit der Zeit, MD5 es wieder, dann nehme den zufälligen Teilstring. Ja, Sie könnte gleiche Passwörter erhalten, aber es ist überhaupt nicht sehr wahrscheinlich.

+0

Wenn Sie eine Teilzeichenfolge eines kryptografisch sicheren Hash-Werts verwenden, wird die Eindeutigkeit des Hashs aufgehoben. Kein Teil eines Hash ist sicherer oder zufälliger als jeder andere. Es ist genauso wahrscheinlich, dass gleiche Passwörter erhalten werden wie bei einem normalen Aufruf eines Zufallszahlengenerators. –

0

Sie könnten Steve Gibson's Over-the-Top-sichere Implementierung eines Passwort-Generators (keine Quelle, aber er hat eine detaillierte Beschreibung, wie es funktioniert) bei https://www.grc.com/passwords.htm interessiert sein.

Die Website erstellt riesige 64-stellige Passwörter, aber da sie völlig zufällig sind, könnten Sie leicht die ersten 8 (oder wie viele) Zeichen für ein weniger sicheres, aber "so zufällig wie möglich" Passwort verwenden.

EDIT: aus dem späten Antwort sehe ich Dir etwas mehr wie eine GUID als ein Passwort benötigen, so ist dies wahrscheinlich nicht das, was Sie wollen ...

1

Jeder Algorithmus in Duplikaten führen.

Kann ich daher vorschlagen, dass Sie Ihren vorhandenen Algorithmus * verwenden und einfach nach Duplikaten suchen?

* Geringfügige Addition: Wenn uniqid() auf der Grundlage der Zeit nicht eindeutig sein kann, schließen Sie auch einen globalen Zähler ein, den Sie nach jedem Aufruf erhöhen. So ist etwas sogar in der gleichen Mikrosekunde anders.

+0

GUID (oder UUIDS) und Sequenzen sind die einzigen zwei Möglichkeiten, Duplikate zu vermeiden, aber Sie sind für jeden anderen hier genannten Algorithmus korrekt. –

+0

Wenn beliebige Bezeichnerlängen zulässig sind, stimme ich zu. Wenn er wie in seinen Beispielen 8 Zeichen behalten möchte, reicht das nicht aus. –

+0

8 Zeichen ist genug für genau 1.099.511.627.776 eindeutige Passwörter, wenn Sie Base32 verwenden, die für manuell eingegebene Daten respektabel ist (32^8) Dies berücksichtigt keine Überprüfung, noch schließt es Muster wie 00000000. –

0

Wie Frank Kreuger kommentiert, gehen Sie mit einem GUID-Generator.

Wie this one

0

Ich sehe noch nicht, warum die Passwörter eindeutig sein? Was ist der Nachteil, wenn 2 Ihrer Benutzer das gleiche Passwort haben?

Dies geht davon aus, dass es sich um Kennwörter handelt, die an Benutzer-IDs gebunden sind, und nicht nur an eindeutige Kennungen. Wenn das ist was Sie suchen, warum nicht GUIDs verwenden?

+0

weil es nicht immer ein Passwort sein kann, aber stattdessen ihre tatsächliche Benutzername/Login-ID oder sagen Sie eine Transaktions-ID. Beide sind im Grunde ein Benutzername, so dass sie eindeutig sein müssen. Ich habe die Datenbank-Setup nur eindeutige Passwörter akzeptieren , aber wieder kann ich nicht davon ausgehen, dass es sich um ein Dat handelt Ich kann darauf zugreifen. Die andere Sache ist, ich will nur 7 bis vielleicht 15 Zeichen. GUIDs sind in der Regel viel länger und werden daher am Ende nicht eindeutig sein. –

0

glaube ich, dass ein Teil Ihrer Frage ist, dass Sie uns eine einzigartige Funktion für zwei getrennte Anwendungen versuchen ... Passwörter und TRANSACTION_ID

diese wirklich sind zwei verschiedene Problembereiche und es ist wirklich nicht am besten versuche sie gemeinsam anzugehen.

0

Ich wollte vor kurzem eine schnelle und einfache Zufalls eindeutigen Schlüssel, damit ich das folgende tat:

$ukey = dechex(time()) . crypt(time() . md5(microtime() + mt_rand(0, 100000))); 

im Grunde also habe ich die Unix-Zeit in Sekunden zu erhalten und eine zufällige md5 Zeichenfolge von Zeit + Zufallszahl generiert hinzufügen . Es ist nicht das beste, aber für Anfragen mit niedriger Frequenz ist es ziemlich gut. Es ist schnell und funktioniert.

Ich habe einen Test, wo ich Tausende von Schlüsseln generieren würde und dann nach Wiederholungen suchen, und mit etwa 800 Tasten pro Sekunde gab es keine Wiederholungen, also nicht schlecht. Ich denke, es hängt total von mt_rand()

Ich verwende es für einen Umfrage-Tracker, wo wir eine Einreichungsrate von etwa 1000 Umfragen pro Minute bekommen ... so für jetzt (kreuzt Finger) gibt es keine Duplikate. Natürlich ist die Rate nicht konstant (wir erhalten die Einreichungen zu bestimmten Tageszeiten), also ist dies nicht ausfallsicher oder die beste Lösung ... der Tipp verwendet einen inkrementellen Wert als Teil des Schlüssels (in meinem Fall Ich habe Zeit() benutzt, könnte aber besser sein).

+1

Ich verstehe nicht, warum Sie MD5-Werte benötigen. MD5 ist ein Einweg-Hashing, das eine Signatur erstellt. Achten Sie darauf, dass verschiedene Eingabewerte zur Erstellung derselben Signatur führen können. MD5-Funktionen werden ausgelöst, um zu versuchen, unterschiedliche Ergebnisse zurückzugeben, wenn die Eingabewerte geringfügig voneinander abweichen. Wenn Sie also MD5 hinzufügen, erhöhen Sie die Wahrscheinlichkeit, doppelte Werte zu erhalten. –

0

Ingoring den Crypten Teil, der hat nicht viel mit dem Erstellen einer eindeutigen Wert zu tun, in der Regel verwende ich diese:

function GetUniqueValue() 
{ 
    static $counter = 0; //initalized only 1st time function is called 
    return strtr(microtime(), array('.' => '', ' ' => '')) . $counter++; 
} 

Wenn in demselben Prozess $ Zähler genannt erhöht wird, so ist Wert immer eindeutig in demselben Prozess .

Wenn Sie in verschiedenen Prozessen aufgerufen werden, müssen Sie wirklich Pech haben, um 2 micrimetime() -Aufruf mit den gleichen Werten zu erhalten, denken Sie, dass microtime() Aufrufe normalerweise unterschiedliche Werte auch beim Aufruf in demselben Skript haben.