Einen Identifier wählen: UUIDs, kurze IDs und die, die Informationen preisgeben

Welche UUID-Version du nehmen solltest, warum v4-Kollisionen praktisch keine Sorge sind, was fortlaufende Ganzzahlen verraten, wie Alphabete für kurze IDs abwägen und wo Zufallsbits herkommen müssen.

Nimm eine UUID v4 für alles Interne, eine v7, wenn der Identifier der Primärschlüssel einer großen Tabelle ist, und einen kurzen Code aus einem eingeschränkten Alphabet, wenn ein Mensch ihn vorlesen muss. Fortlaufende Ganzzahlen sind die Option, die du bei allem Öffentlichen vermeiden solltest.

UUID-Versionen, die zählen

Eine UUID hat 128 Bit. Vier davon tragen die Version und zwei die Variante, keine Version hat also alle 128 zur Verfügung.

VersionWas sie enthältWann du sie nimmst
v160-Bit-Zeitstempel, 14-Bit-Taktsequenz, 48-Bit-Node-ID (die MAC-Adresse)Nur für Altdaten
v3 / v5Ein MD5- oder SHA-1-Hash aus einem Namensraum und einem NamenWenn deterministische IDs gebraucht werden
v4122 Zufallsbits, sonst nichtsStandard, wenn sich nichts ableiten lassen soll
v748-Bit-Millisekundenzeitstempel, dann 74 ZufallsbitsSchlüssel, bei denen die Einfügereihenfolge zählt

v1 ist die mahnende Version. Sie enthält den Erzeugungszeitpunkt und, in den meisten Implementierungen, die MAC-Adresse der Maschine, die sie erzeugt hat; so halfen solche Identifier 1999 dabei, den Autor des Melissa-Virus aufzuspüren. v7, 2024 in RFC 9562 standardisiert, veröffentlicht den Erzeugungszeitpunkt absichtlich: das ist ihr Merkmal und ihr Preis.

Die Frage der Kollisionen

Eine v4-UUID hat 122 Zufallsbits, es gibt also 2^122 davon, rund 5,3 x 10^36. Entscheidend ist die Geburtstagsschranke, nicht die Größe des Raums: Die Wahrscheinlichkeit, dass zwei von n Werten übereinstimmen, liegt bei etwa n zum Quadrat geteilt durch 2^123. Eine Billion erzeugter UUIDs bringt etwa eine Chance von eins zu zehn Billionen auf ein Duplikat, und für die Chance eines Münzwurfs braucht es rund 2,7 x 10^18 Werte, also etwa 85 Jahre bei einer Milliarde pro Sekunde.

„Praktisch kein Problem“ ist trotzdem nicht „unmöglich“, und die Lücke liegt nie in der Rechnung. Duplikate kommen vom Generator: ein fester Seed, eine virtuelle Maschine, die samt ihrem Entropiepool geklont wurde, ein Container-Image, das gespeicherten PRNG-Zustand mitliefert. Eindeutigkeit gehört der Zufallsquelle, nicht dem Format, behalte den Unique-Constraint auf der Spalte also bei.

Sortierung, Indexlokalität und Informationsabfluss

Zufällige Identifier streuen. In einem B-Baum-Index landet jedes Insert auf einer zufälligen Blattseite, das Working Set ist also der gesamte Index statt nur sein rechter Rand, die Cache-Trefferquoten sinken und Seiten werden geteilt. Ein Schlüssel, der mit der Zeit ansteigt, hängt an einer Stelle an und hält dieselben wenigen Seiten warm. Deshalb gibt es v7 und ULID; ULID besteht aus 48 Bit Millisekundenzeitstempel plus 80 Zufallsbits, geschrieben als 26 sortierbare Zeichen in Crockford base32.

Der Preis ist Vorhersagbarkeit: Eine zeitlich sortierte ID veröffentlicht, wann ihr Datensatz angelegt wurde, eine Handvoll davon verrät also Anmelderaten und stille Stunden. Wenn das zählt, nimm v4 und zahle den Preis beim Index.

Fortlaufende Ganzzahlen gehen weiter. /invoices/1041 sagt, dass du etwa tausend Rechnungen ausgestellt hast, und zwei IDs im Abstand einer Woche ergeben deine Wachstumsrate. Schlimmer noch: Ein Angreifer kann 1040 anfragen. Wenn der Server diesen Datensatz zurückgibt, weil er existiert und der Aufrufer angemeldet ist, ohne zu prüfen, wem er gehört, ist das ein Fehler in der Zugriffskontrolle, katalogisiert als unsichere direkte Objektreferenz. Eine nicht erratbare ID ist keine Autorisierungsprüfung, aber sie verhindert, dass jemand die Tabelle durchläuft.

Auch Slugs sind Identifier, und sie geben nichts über Mengen preis, wenn sie sauber gebaut sind: Akzente aufgelöst, Kleinschreibung, Satzzeichen zu Bindestrichen zusammengezogen, so wie der Slug Generator es macht. Halte einen Slug nach der Veröffentlichung stabil; ihn zu ändern zerstört eingehende Links.

Kurze IDs, Alphabete und Länge

Jedes Zeichen eines Zufallscodes ist log2 der Alphabetgröße wert: 5,95 Bit für base62, 5 für base32, 4 für hexadezimal. Länge und Alphabet bestimmen die Kollisionswahrscheinlichkeit bei einer gegebenen Menge.

Länge (base62)Verschiedene WerteBitsKollisionschance innerhalb von 1 Milliarde IDs
82,2 x 10^1443,7Sicher
108,4 x 10^1759,5Etwa 45 %
123,2 x 10^2171,5Etwa 1 zu 6.500
164,8 x 10^2895,3Etwa 1 zu 100 Milliarden

Das setzt voraus, dass jedes Zeichen unabhängig zufällig ist; ein Präfix wie inv_ bringt null Bit.

Für alles, was ein Mensch liest, ist base62 das falsche Alphabet. 0 und O, 1 und l und I sind Übertragungsfehler, die nur darauf warten zu passieren, und ein Code, der Groß- und Kleinschreibung unterscheidet, übersteht kein Telefonat. Crockford base32 lässt I, L, O und U weg und akzeptiert bei der Eingabe beide Schreibweisen; das ist das zusätzliche Zeichen wert.

Woher die Zufallsbits kommen

Math.random() ist keine kryptografische Quelle. V8 implementiert es mit xorshift128+, dessen interner Zustand sich aus einer kurzen Folge von Ausgaben rekonstruieren lässt, wonach jeder künftige Wert vorhersagbar ist. Für ein Demo-Mischen oder einen Platzhalter in Ordnung. Falsch für einen Session-Identifier, einen API-Schlüssel, einen Reset-Link oder ein Token.

// Browsers, Node 19+, Deno and Bun
const id = crypto.randomUUID();

const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);

Anderswo: crypto.randomBytes in Node, secrets.token_urlsafe in Python, crypto/rand in Go, SecureRandom in Java, random_bytes in PHP. Der UUID Generator erzeugt kryptografisch zufällige v4-Werte, und der Password Generator nutzt dieselbe Browser-API; Random Numbers ist zum Stichproben ziehen da, nicht für Geheimnisse.

Eine Falle, wenn du es selbst baust: Ein Zufallsbyte per % 62 auf ein Alphabet mit 62 Zeichen abzubilden verzerrt zugunsten der ersten acht Zeichen; nutze Verwerfungsstichproben.

Platzhalter- und Beispieldaten

Lorem ipsum ist verstümmelter Cicero, und es überlebt, weil es unlesbar ist: Text, der wie Sprache aussieht, ohne Sprache zu sein, erlaubt es, ein Layout nach Form und Zeilenlänge zu beurteilen statt nach seinen Sätzen, und genau das erzeugt der Lorem-Ipsum-Generator. Tausche vor der Freigabe realistische Texte ein, denn Platzhalterlatein verbirgt den Überlauf, den eine echte Überschrift verursachen wird.

Erfundene Daten brauchen eine Regel: Sie dürfen niemals mit dem Echten verwechselbar sein.

  • Kartennummern stammen aus dem veröffentlichten Testbereich eines Zahlungsdienstleisters oder scheitern glatt an der Luhn-Prüfung. Eine zufällige 16-stellige Zahl, die die Luhn-Prüfung besteht, gehört jemandem.
  • Nationale Kennnummern nutzen reservierte Bereiche. US-amerikanische Sozialversicherungsnummern, die mit 000, 666 oder 900 bis 999 beginnen, werden nie vergeben.
  • Nutze example.com und seine Geschwister, reserviert durch RFC 2606, und den Dokumentationsblock 192.0.2.0/24.

Testdaten erreichen die Produktion öfter als erwartet: ein Seed-Skript, das auf die falsche Datenbank zeigt, ein Platzhalter, der in einer E-Mail-Vorlage stehen bleibt und an den ganzen Verteiler geht. Gefälschte Datensätze sollten offensichtlich gefälscht aussehen, damit ein Mensch einen davon bemerkt, bevor der Support darauf reagiert.

QR-Codes in Kürze

Ein QR-Code ist ein Raster aus Modulen, in den Versionen 1 bis 40, von 21x21 bis 177x177. Die Länge der Nutzdaten bestimmt die Version, und bei fester Druckgröße bedeutet eine höhere Version kleinere Module, die besseren Druck und einen näheren Scan erfordern. Kürze die URL, bevor du sie dem QR Code Generator gibst, und beachte, dass der alphanumerische Modus nur Großbuchstaben kennt, HTTPS://EXAMPLE.COM also kompakter codiert als die Kleinschreibweise.

Die Fehlerkorrektur hat vier Stufen und stellt etwa 7 % (L), 15 % (M), 25 % (Q) und 30 % (H) eines beschädigten Codes wieder her. Redundanz kostet Kapazität, eine höhere Stufe drückt dieselben Nutzdaten also in eine dichtere Version. M ist der übliche Standard; wähle Q oder H für kleinen Druck, gewölbte Oberflächen oder ein Logo über der Mitte, was funktioniert, weil die Redundanz es auffängt.

Zwei physische Anforderungen entscheiden, ob ein Code gelesen wird. Die Ruhezone ist ein freier Rand von vier Modulen auf jeder Seite, den der Decoder nutzt, um die Begrenzung zu finden; ein Code, der direkt an einen Rahmen oder ein Foto stößt, scheitert deshalb oft. Der Kontrast muss echt dunkel auf echt hell sein: Hellblau auf Weiß ist ein häufiger Fehler, und viele Decoder verweigern invertierte Codes.