Universally Unique Identifier
Ein Universally Unique Identifier (UUID) ist eine 128-Bit-Zahl, welche zur Identifikation von Informationen in Computersystemen verwendet wird. Der Ausdruck Globally Unique Identifier (GUID) wird ebenfalls benutzt, typischerweise im Zusammenhang mit Microsoft (z. B. Software, Registry).
Bei der Generierung nach den Standardmethoden können UUIDs für praktische Zwecke als global eindeutig angenommen werden. Obwohl die Wahrscheinlichkeit, dass ein UUID dupliziert wird, nicht null ist, ist sie so gering, dass die Wahrscheinlichkeit für eine Kollision zumeist vernachlässigbar ist. Ein Vorteil von UUIDs ist die – im Gegensatz zu den meisten anderen Nummerierungsschemata – Unabhängigkeit von einer zentralen Registrierungsstelle oder Koordinierung zwischen den Parteien.
Daher kann jeder einen UUID erstellen und ihn verwenden, um etwas mit der größtmöglichen Gewissheit zu identifizieren, dass der Bezeichner nicht einen anderen Bezeichner dupliziert, der bereits erstellt wurde oder wird, um etwas anderes zu identifizieren. Informationen, die von unabhängigen Parteien mit UUIDs gekennzeichnet wurden, können daher später in einer einzigen Datenbank zusammengefasst oder auf demselben Kanal mit einer vernachlässigbaren Wahrscheinlichkeit von Duplikaten übertragen werden.
Die Verwendung von UUIDs und GUIDs ist weit verbreitet. Viele Computerplattformen bieten Unterstützung beim Generieren und Parsen ihrer Textdarstellung.
Er wurde von der Open Software Foundation (OSF) als Teil des Distributed Computing Environment (DCE) standardisiert und ist jetzt in RFC 4122 geregelt.
Ein UUID besteht aus einer 16-Byte-Zahl, die hexadezimal notiert und in fünf Gruppen unterteilt wird. In seiner Normalform sieht ein UUID beispielsweise so aus:
550e8400-e29b-11d4-a716-446655440000
Geschichte und Standardisierung
UUID sind als Teil des Standards ISO/IEC 11578:1996 “Information technology – Open Systems Interconnection – Remote Procedure Call (RPC)” und als separater Standard ISO/IEC 9834-8:2005 dokumentiert. Die IETF hat das auf UUID basierende RFC 4122 veröffentlicht.
Das originale (Version 1) Generierungsschema für UUID war, die UUID-Version mit der MAC-Adresse des Computers, der den UUID generiert, und der Anzahl der 100-Nanosekunden-Intervalle seit Beginn des Gregorianischen Kalenders aneinanderzuhängen. In der Praxis ist der eigentliche Algorithmus komplizierter. Dieses Schema wurde kritisiert, weil es sowohl die Identität des generierenden Computers als auch den Zeitpunkt der Generierung preisgibt.
Mehrere andere Algorithmen zur Generierung wurden entwickelt und flossen in den Standard ein, so ein Schema, welches nur auf Zufallszahlen basiert (Version 4 UUID), und Schemata, in denen der UUID aus einem beliebigen String (z. B. DNS-Eintrag, URL, ISO OID, „X.500 Distinguished Names“, aber auch jeder beliebigen anderen Semantik, sofern ein Basis-UUID dafür definiert wird) über MD5- (Version 3 UUID) oder SHA-1- (Version 5 UUID) Hashwerte hergeleitet wird.
Das Release 5.0 von Java stellt eine Klasse zur Verfügung, die 128 Bit breite UUID generiert. Die API-Dokumentation für die Klasse java.util.UUID
[1] verweist auf RFC 4122. Auch viele andere Sprachen stellen fertige Routinen zur Generierung von UUID bereit.
Variante: Microsoft GUID
Microsoft verwendet in seinem Component Object Model ebenfalls UUIDs, dort auch GUID genannt. Allerdings entsprechen diese IDs zum Teil einer eigenen Spezifikation. Die hier beschriebenen UUIDs sind an den obersten beiden Bits des Feldes clock_seq_high_and_reserved
erkennbar. Sie haben stets den Wert 10; in der Hexadezimaldarstellung ist daher die erste Hexziffer der vierten Zahl stets zwischen 8hex und Bhex, z. B.: 5945c961-e74d-478f-8afe-da53cf4189e3. Die von Microsoft verwendeten historischen UUIDs haben in den obersten drei Bits dieses Feldes den Wert 110, in der Hexadezimaldarstellung ist daher die erste Hexziffer der vierten Zahl entweder Chex oder Dhex. Beispiel: Der GUID des IUnknown
-Interfaces im COM besitzt den UUID 00000000-0000-0000-C000-000000000046.
Aufbau
RFC 4122 beschreibt den Aufbau eines UUID. Die Namen der einzelnen Felder orientieren sich an der ursprünglichen UUID-Version 1 und sind bei den heute vorwiegend verwendeten zufällig generierten UUIDs nur noch von historischem Interesse.
Offset | Feldname | Datentyp | Beschreibung |
---|---|---|---|
0 | time_low | uint32_t | Zeitstempel, niederstwertige 32 Bits |
4 | time_mid | uint16_t | Zeitstempel, mittlere 16 Bits |
6 | time_hi_and_version | uint16_t | Oberste Bits des Zeitstempels in den unteren 12 Bits des Feldes, die oberen 4 Bits dienen als Versionsbezeichner |
8 | clock_seq_high_and_reserved | uint8_t | Oberste 6 Bits der Clocksequenz (die obersten 2 Bits des Feldes sind in der hier beschriebenen UUID-Variante stets 1 0 )
|
9 | clock_seq_low | uint8_t | Untere 8 Bits der Clocksequenz |
10 | node | uint48_t | Eindeutige Node-Identifikationsnummer |
Die obersten vier Bits im Feld time_hi_and_version
geben dabei die sogenannte Version des UUID an. Strenggenommen ist dies keine Version, sondern eine Art UUID-Subtyp. Folgende 5 Versionen sind bisher definiert worden:
Version | Beschreibung |
---|---|
1 | ursprünglicher, zeitstempelbasierter UUID |
2 | DCE Security version |
3 | namensbasiert, MD5-gehasht |
4 | zufälliger oder pseudozufälliger UUID |
5 | namensbasiert, SHA1-gehasht |
Darüber hinaus wird die Einführung von weiteren Versionsnummern diskutiert, wie in folgender Tabelle mit Stand im Jahr 2022 dargestellt.[2]
Version | Beschreibung |
---|---|
6 | zeitstempelbasierend wie Version 1, aber mit anderer Anordnung der Datenfelder |
7 | zeitstempelbasierend auf der Unixzeit |
8 | für experimentelle oder herstellerspezifische Anwendungen |
Zeitstempelbasierte UUIDs
Der Zeitstempel ist ein 60-Bit-Wert, der die seit dem 15. Oktober 1582 (Einführung des heutigen Gregorianischen Kalenders) vergangenen 100-ns-Intervalle zählt. Um die Zeitstempel eindeutig zu halten, falls die Systemzeit einmal zurückgestellt werden muss, gibt es ein Feld Clock sequence, welches in diesem Fall entweder um 1 erhöht wird oder auf einen neuen (pseudo)zufälligen Wert gesetzt werden soll. Die Node-ID soll die MAC-Adresse einer der im System verbauten Netzwerkkarten sein oder ein pseudozufälliger Wert, falls das System keine MAC-Adresse besitzt.[3]
(Pseudo)zufällig generierte UUIDs (Version 4)
Hierbei werden sämtliche Bits, die nicht vom UUID-Format auf feste Werte gesetzt werden, durch (pseudo-)zufällige Werte besetzt.
Obwohl die Eindeutigkeit für einen so generierten UUID nicht garantiert ist, ist die Gesamtzahl der zufällig generierbaren UUIDs mit so groß, dass die Wahrscheinlichkeit der Erzeugung zweier gleicher UUIDs sehr klein ist, sofern die verwendeten Zufallszahlenalgorithmen gleichverteilte Zufallszahlen liefern. Daher können UUIDs beliebig ohne zentrales Kontrollorgan erzeugt und zur Kennzeichnung eingesetzt werden, ohne relevante Gefahr zu laufen, dass derselbe UUID für etwas anderes verwendet wird. Mit UUID markierte Informationen können somit später in einer einzigen Datenbank zusammengeführt werden, ohne Bezeichnerkonflikte auflösen zu müssen.
Beispiele für Implementierung des UUID-Standards sind:
- Microsofts Globally Unique Identifier (GUID)
- Die Java-Klasse
java.util.UUID
- Die Qt-Klasse
QUuid
- Die Linux-Datei
/proc/sys/kernel/random/uuid
[4] - Unter FreeBSD implementiert als uuid(3)
Namensbasierte UUIDs (Version 3 und 5)
Hierbei wird ausgehend von einem nicht näher bestimmten Namen ein UUID generiert. Namen sind innerhalb eines zugewiesenen Namensraums eindeutige Bezeichner für ein Objekt, eine Ressource oder Ähnliches. Ausgehend von einem UUID für den Namensraum wird aus dem Namen ein UUID generiert, indem eine Bytesequenz aus der Namensraum-UUID und dem Namen selbst gebildet wird und diese Bytesequenz dann mit MD5 oder SHA1 gehasht wird. Der Hash wird dann auf definierte Weise auf die verfügbaren UUID-Bits verteilt.
RFC 4122 enthält beispielhafte Namensraum-UUIDs für die Namensräume DNS, URL, ISO OID und „X.500 Distinguished Names“.
Soll beispielsweise aus dem DNS-Namen www.example.org
ein UUID-Version 5 generiert werden, so ist wie folgt vorzugehen:
- Namespace-UUID für „DNS“-Namen ist 6ba7b810-9dad-11d1-80b4-00c04fd430c8.
- An diese Bytefolge wird die Bytefolge für den Namen
www.example.org
angehängt (Bytes vom Namespace-UUID in fett):0x6b 0xa7 0xb8 0x10 0x9d 0xad 0x11 0xd1 0x80 0xb4 0x00 0xc0 0x4f 0xd4 0x30 0xc8
0x77 0x77 0x77 0x2e 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65 0x2e 0x6f 0x72 0x67
. - Diese Bytesequenz ist mit SHA1 zu hashen. Das Ergebnis ist folgender SHA1-Hash: 74738ff55367e9589aee98fffdcd187694028007
- Die Bits des SHA1-Hashes sind auf die verfügbaren Bits der UUID-Version 5 aufzuteilen.
- Generierter UUID: 74738ff5-5367-5958-9aee-98fffdcd1876. (Die fett markierten Stellen enthalten feste Bits aus UUID-Variante und -Version.)
Kollisionen
Kollisionen entstehen, wenn derselbe UUID mehr als einmal generiert und verschiedenen Referenzobjekten zugewiesen wird.
Bei Version 1 und 2 kann eine Kollision nur entstehen, wenn von der Standardimplementation abgewichen wird, entweder absichtlich oder unabsichtlich.
Bei den Hash-basierten Versionen 3 und 5 sowie der pseudo-zufälligen Version 4 können Kollisionen auch ohne Abweichungen in der Implementierung entstehen. Jedoch ist die Wahrscheinlichkeit dafür so gering, dass sie normalerweise ignoriert werden kann. Die Wahrscheinlichkeit hierfür kann analog zum Geburtstagsproblem genau berechnet werden.[5]
Zum Beispiel beträgt die Anzahl von Version-4 UUIDs, die berechnet werden müssen, um eine 50 %-Wahrscheinlichkeit von mindestens einer Kollision zu haben, 2,71 Trillionen. Dies berechnet sich wie folgt:
Fehler beim Parsen (Konvertierungsfehler. Der Server („https://wikimedia.org/api/rest_“) hat berichtet: „Cannot get mml. Server problem.“): {\displaystyle n\approx {\frac {1}{2}}+{\sqrt {{\frac {1}{4}}+2\times \ln(2)\times 2^{122}}}\approx 2{,}71\times 10^{18}.}
Würde man 1 Milliarde UUIDs pro Sekunde generieren, bräuchte man 85 Jahre, um diese Anzahl an UUIDs zu generieren.
Die kleinste Anzahl von Version-4 UUIDs, die für die Wahrscheinlichkeit, eine Kollision zu finden, erzeugt werden müssen, wird durch diese Formel approximiert:
Daher beträgt die Wahrscheinlichkeit für ein Duplikat eins aus einer Milliarde bei 103 Billionen Version-4 UUIDs.
Weblinks
- Syntax and semantics of the DCE variant of Universal Unique Identifiers (UUIDs) (englisch)
- RFC 4122 – A Universally Unique IDentifier (UUID) URN Namespace (englisch)
- ITU-T Recommendation X.667 (08/2008) (englisch)
Einzelnachweise
- ↑
Class
UUID
Java API Specification bei Oracle.
(For more information including algorithms used to create UUIDs, see RFC 4122: A Universally Unique IDentifier (UUID) URN Namespace, section 4.2 “Algorithms for Creating a Time-Based UUID”.) - ↑ a b New UUID Formats, draft-peabody-dispatch-new-uuid-format-04. 23. Juni 2022, abgerufen am 30. Juni 2022.
- ↑ Ausführlichere Beschreibung Zeitstempelbasierter UUIDs (in Englisch)
- ↑ Linux Programmer’s Manual. RANDOM(4). In: The Linux Programming Interface. Michael Kerrisk, 22. März 2021, abgerufen am 19. Oktober 2021 (englisch).
- ↑ Paulo Jesus, Carlos Baquero, Paula Almaeida: ID Generation in Mobile Environments. In: Repositorium.Sdum.Uminho.pt .