it-swarm.com.de

UUID-Kollisionen

Hat jemand wirklich nach der Wahrscheinlichkeit von UUID-Kollisionen gesucht, insbesondere mit (zufälligen) UUIDs der Version 4, da die von uns verwendeten Zufallszahlengeneratoren nicht wirklich zufällig sind und möglicherweise Dutzende oder Hunderte identischer Computer denselben Code ausführen UUIDs generieren?

Meine Mitarbeiter betrachten das Testen auf UUID-Kollision als reine Zeitverschwendung, aber ich habe immer Code eingegeben, um eine doppelte Schlüsselausnahme aus der Datenbank abzufangen und es erneut mit einer neuen UUID zu versuchen. Dies wird das Problem jedoch nicht lösen, wenn die UUID aus einem anderen Prozess stammt und sich auf ein reales Objekt bezieht.

33
Paul Tomblin

Wikipedia hat einige Details:

http://en.wikipedia.org/wiki/Universally_unique_identifier

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

Die Wahrscheinlichkeit gilt jedoch nur, wenn die Bits vollkommen zufällig sind. Der in der anderen Antwort verknüpfte RFC http://tools.ietf.org/html/rfc4122#page-14 definiert dies jedoch für Version 4:

"4.4. [...] Die UUID der Version 4 dient zum Generieren von UUIDs aus wirklich zufälligen oder pseudozufälligen Zahlen. [...] Setzen Sie alle anderen Bits auf zufällig (oder pseudozufällig) ausgewählte Werte."

Dies ermöglicht so ziemlich alles vom xkcd-Zufallsgenerator http://xkcd.com/221/ bis zu einem Hardwaregerät mit Quantenrauschen. Die Sicherheitsüberlegungen im RFC:

"6. Verteilte Anwendungen, die UUIDs auf verschiedenen Hosts generieren, müssen bereit sein, sich auf allen Hosts auf die Zufallszahlenquelle zu verlassen. Wenn dies nicht möglich ist, sollte die Namespace-Variante verwendet werden."

Ich habe das so gelesen: Du bist allein. Sie sind für Ihren Zufallsgenerator in Ihrer eigenen Anwendung verantwortlich, aber dies und alles andere basiert auf Vertrauen. Wenn Sie Ihrer eigenen Fähigkeit nicht vertrauen, den Zufallsgenerator Ihrer Wahl richtig zu verstehen und zu verwenden, ist es in der Tat eine gute Idee, nach Kollisionen zu suchen. Wenn Sie dem Programmierer der anderen Prozesse nicht vertrauen, suchen Sie nach Kollisionen oder verwenden Sie eine andere UUID-Version.

18
Secure

Sie sollten auf jeden Fall erkennen, ob eine Kollision auftritt, und Ihre Anwendung sollte in diesem Fall eine Ausnahme auslösen. Z.B. Wenn die UUID als Primärschlüssel in der Datenbank verwendet wird, sollte die Datenbank beim Einfügen einer kollidierenden ID einen Fehler auslösen.

Ich würde jedoch glauben, dass das Schreiben von Code zum Generieren einer neuen UUID im Falle einer Kollision und der erneute Versuch, Zeitverschwendung zu sein. Die Wahrscheinlichkeit einer Kollision ist so gering, dass das Auslösen einer Ausnahme eine durchaus vernünftige Möglichkeit wäre, damit umzugehen.

Denken Sie daran, es ist nicht nur eine Verschwendung Ihrer eigenen Zeit, den Code zu schreiben, sondern es macht den Code auch komplexer, was es für die nächste Person schwieriger macht, ihn zu lesen, fast ohne Gewinn.

11
Pete

Das ist eine sehr gute Frage. Ich glaube nicht, dass es in der Eile angemessen berücksichtigt wurde, UUIDs überall zu verwenden. Ich habe keine solide Forschung gefunden.

Ein Vorschlag: Gehen Sie hier sehr vorsichtig vor und kennen Sie Ihre Kryptographie gut. Wenn Sie eine 128-Bit-UUID verwenden, sagt uns der 'Geburtstagseffekt', dass eine Kollision wahrscheinlich ist, nachdem Sie ungefähr 2 ^ 64 Schlüssel generiert haben, vorausgesetzt, Sie haben 128 Bit Entropie in jedem Schlüssel.

Es ist eigentlich ziemlich schwierig sicherzustellen, dass dies der Fall ist. Echte Zufälligkeit kann durch (a) radioaktiven Zerfall (b) zufälliges Hintergrundfunkrauschen erzeugt werden, das häufig kontaminiert ist, es sei denn, Sie sind vorsichtig (c) geeignet ausgewähltes elektronisches Rauschen, z. entnommen aus einer in Sperrrichtung vorgespannten Zenerdiode. (Ich habe mit dem letzten gespielt und es funktioniert wie ein Zauber, übrigens).

Ich würde Aussagen wie "Ich habe dies seit einem Jahr nicht mehr gesehen" nicht vertrauen, es sei denn, der Benutzer hat etwas generiert, das sich 2 ^ 64 (dh ungefähr 10 ^ 19) Schlüsseln nähert, und sie alle gegeneinander geprüft, a nicht triviale Übung.

Das Problem ist das. Angenommen, Sie haben nur 100 Entropiebits, wenn Sie Ihre Schlüssel mit allen anderen Schlüsseln vergleichen, die alle anderen in einem gemeinsamen Schlüsselbereich generieren. Sie werden Kollisionen in ungefähr 2 ^ 50 sehen, dh. ungefähr 10 ^ 15 Schlüssel. Ihre Chancen auf eine Kollision, wenn Sie Ihre Datenbank mit nur 1000 Milliarden Schlüsseln gefüllt haben, sind immer noch vernachlässigbar. Und wenn Sie dies nicht überprüfen, werden Sie später unerwartete Fehler erhalten, die sich in Ihre Datenbank mit Peta-Row-Größe einschleichen. Dies könnte schwer beißen.

Die Tatsache, dass es mehrere Ansätze zur Erzeugung solcher UUIDs gibt, sollte einen vorübergehenden Anlass zur Sorge geben. Wenn Sie feststellen, dass nur wenige Generatoren "wirklich zufällige" Prozesse mit ausreichender Entropie für eine UUID vom Typ 4 verwenden, sollten Sie übermäßig besorgt sein es sei denn Sie haben den Entropiegehalt des Generators sorgfältig untersucht. (Die meisten Leute werden dies nicht tun oder sogar wissen, wie es geht; Sie könnten mit der DieHarder-Suite beginnen). Verwechseln Sie die Erzeugung von Pseudozufallszahlen NICHT mit der Erzeugung von echten Zufallszahlen.

Es ist wichtig, dass Sie erkennen, dass die eingegebene Entropie die Entropie ist, die Sie haben, und dass eine einfache Störung des Schlüssels durch Anwenden einer kryptografischen Funktion die Entropie nicht verändert. Es ist möglicherweise nicht intuitiv ersichtlich, dass, wenn mein gesamter Raum die Ziffern 0 und 1 umfasst, der Entropiegehalt der gleiche ist wie der der folgenden beiden Zeichenfolgen, vorausgesetzt, dies sind die einzigen beiden Optionen: "Dies ist eine wirklich sehr komplexe Zeichenfolge 293290729382832 * ! @@ # & ^% $$),. m} "und" UND JETZT FÜR ETWAS VOLLSTÄNDIG UNTERSCHIEDLICHES ". Es gibt noch nur zwei Möglichkeiten.

Zufälligkeit ist schwierig, richtig zu machen, und es reicht möglicherweise nicht aus, einfach zu glauben, dass "Experten es sich angesehen haben, es ist daher in Ordnung". Erfahrene Kryptographen (und es gibt nur wenige, die wirklich kompetent sind) geben als erste zu, dass sie häufig etwas falsch machen. Wir vertrauten auf Heartbleed, DigiNotar usw.

Ich denke, Paul Tomblin ist angemessen vorsichtig. Mein 2c.

7
user199506

Das Problem, das Sie haben, ist, dass wenn Sie einen "Zufallszahlengenerator" verwenden und nicht wissen, wie zufällig dieser Generator ist, die Wahrscheinlichkeit einer Kollision tatsächlich unbekannt ist. Wenn die Zufallszahlengeneratoren auf irgendeine Weise korreliert sind, kann sich die Wahrscheinlichkeit einer Kollision dramatisch erhöhen - möglicherweise viele, viele Ordnungen oder Größenordnungen.

Selbst wenn Sie eine sehr geringe Kollisionswahrscheinlichkeit haben, haben Sie ein grundlegendes Problem: Die Wahrscheinlichkeit ist NICHT 0. Dies bedeutet, dass eine Kollision irgendwann auftreten wird, sie wird nur nicht sehr oft auftreten.

Je häufiger Sie die UUIDs generieren und verwenden, desto eher wird eine Kollision wahrscheinlich. (1 pro Jahr zu generieren bedeutet eine längere Wartezeit als eine Million pro Sekunde zu generieren, wenn alle anderen Dinge gleich sind).

Wenn diese Wahrscheinlichkeit endlich und unbekannt ist und Sie viele UUIDs verwenden, müssen Sie die Folgen einer Kollision berücksichtigen. Wenn es nicht akzeptabel ist, eine Ausnahme auszulösen und eine Geschäftsanwendung herunterzufahren, tun Sie es nicht! (Beispiele aus dem Kopf: "Es ist in Ordnung, den Webserver während des Aktualisierens eines Bibliotheks-Check-ins herunterzufahren ... es kommt nicht oft vor" und "Es ist in Ordnung, das Lohn- und Gehaltsabrechnungssystem mitten in herunterzufahren." den Gehaltslauf machen ". Diese Entscheidungen können karrierebeschränkende Schritte sein.)

Abhängig von Ihrer Anwendung kann es jedoch zu einem schlimmeren Fall kommen. Wenn Sie auf das Vorhandensein einer UUID testen (dh eine Suche durchführen) und dann eine neue erstellen, falls noch keine vorhanden ist - was häufig genug ist -, stellen Sie möglicherweise fest, dass Sie Datensätze verknüpfen oder Beziehungen herstellen , wenn Sie tatsächlich 2 Dinge über eine UUID verbinden, die nicht verbunden werden sollte. Dies ist etwas, bei dem das Auslösen einer Ausnahme nichts löst und Sie irgendwo ein nicht nachweisbares Durcheinander haben. Dies führt zu Informationslecks und kann sehr peinlich sein. (Beispiel: Melden Sie sich bei Ihrer Bank an und stellen Sie fest, dass Sie den Kontostand eines anderen Kontos sehen können! Schlecht!)

Zusammenfassung: Sie müssen die Art und Weise, wie Ihre UUIDs verwendet werden, und die Folgen einer Kollision berücksichtigen. Dies bestimmt, ob Sie darauf achten sollten, Kollisionen zu erkennen und zu vermeiden, im Falle einer Kollision einfache Maßnahmen zu ergreifen oder nichts zu tun. Eine einfache, einheitliche Lösung ist unter bestimmten Umständen wahrscheinlich unangemessen.

6
quickly_now

Es gibt zwei Probleme:

  1. Qualität der verwendeten Zufallszahlengeneratoren.

  2. Anzahl der UUIDs, die generiert werden können.

Eine "zufällige" UUID hat 122 zufällige Bits. Unter der Annahme einer perfekten Zufälligkeit können Sie die erste Kollision bei etwa 2 ^ 61 generierten UUIDs erwarten (das ist die Quadratwurzel von 2 ^ 122). Wenn jeder auf dieser Erde eine UUID pro Sekunde generieren würde, wären das 10.000.000.000 * 365 * 24 * 60 * 60 = 315360000000000000 UUIDs pro Jahr, was ziemlich nahe an 2 ^ 58 liegt. Das heißt, nach einigen Jahren würden Sie die ersten Kollisionen bekommen. Wenn Ihre Anwendung nicht in die Nähe dieser Zahlen kommt, können Sie ziemlich sicher sein, dass Sie keine Kollision bekommen, wenn Ihr Zufallsgenerator von anständiger Qualität ist.

Apropos Zufallszahlengenerator: Wenn Sie die Standardgeneratoren für C-Bibliotheken (direkt, indirekt oder ähnliche Generatoren) verwenden und diese wahrscheinlich mit der Zeit säen, sind Sie überfordert. Diese können nicht auf genügend Entropie zurückgreifen, um Kollisionen zu vermeiden. Wenn Sie jedoch unter Linux arbeiten, lesen Sie einfach 16 Datenbytes aus /dev/urandom: Dies basiert auf einem Entropiepool, der vom Kernel bewegt wird und auf einige echte zufällige Ereignisse zugreifen kann. Es sei denn, Sie generieren normalerweise UUIDs sehr, sehr früh in der Startsequenz, /dev/urandom sollte sich wie eine echte Zufallsquelle verhalten.