JS
() =>
JavaScript · Web Crypto API · UUID · Sicherheit
crypto.randomUUID()
Sichere UUIDs nativ in JavaScript generieren

Math.random() ist für IDs ungeeignet – es nutzt einen vorhersagbaren Pseudozufallsgenerator. crypto.randomUUID() liefert echte UUID v4 aus einem kryptografisch sicheren Zufallsgenerator, ohne externe Abhängigkeiten, in Browser und Node.js gleichermaßen.

8 Min. Lesezeit crypto.randomUUID · UUID v4 · Web Crypto · getRandomValues Chrome 92+ · Firefox 95+ · Safari 15.4+ · Node.js 14.17+

1. Warum UUIDs und warum kryptografisch sicher?

Eindeutige Bezeichner sind in modernen Web-Apps allgegenwärtig: temporäre IDs für optimistisches UI-Rendering, Idempotenz-Tokens für API-Requests, Session-Nonces, Correlation-IDs für verteiltes Logging, Datenbankschlüssel bei clientseitiger Datenerstellung. Das grundlegende Anforderungsprofil ist immer dasselbe: die ID muss einmalig genug sein, dass Kollisionen in der Praxis nicht auftreten, und sie darf nicht vorhersagbar sein, damit Angreifer keine IDs erraten oder enumerieren können.

crypto.randomUUID() erfüllt beide Anforderungen. Es verwendet einen kryptografisch sicheren Pseudozufallsgenerator (CSPRNG), der vom Betriebssystem bereitgestellt wird – denselben, der für kryptografische Schlüssel verwendet wird. Das ist ein fundamentaler Unterschied zu Math.random(), das einen deterministischen Algorithmus nutzt, der mit bekanntem Seed vollständig vorhersagbar ist. Für IDs, die keine Sicherheitsfunktion erfüllen, ist Vorhersagbarkeit akademisch. Aber für Tokens, Nonces und IDs, die als Geheimnis gelten, ist crypto.randomUUID() das korrekte Werkzeug – und das mit einer Zeile Code.

2. UUID v4: Aufbau und Format

Eine UUID (Universally Unique Identifier) nach RFC 4122 ist eine 128-Bit-Zahl, die in einem standardisierten Textformat dargestellt wird: acht Hexadezimalzeichen, gefolgt von drei Gruppen aus vier Zeichen und abschließend zwölf Zeichen, getrennt durch Bindestriche – insgesamt 36 Zeichen. Das Format lautet xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx, wobei M die Version (bei v4 immer 4) und die ersten beiden Bits von N die Variante (bei RFC 4122 immer 10 binär, also 8, 9, a oder b hex) kodieren.

UUID v4 nutzt 122 der 128 Bits für Zufallswerte – die übrigen 6 Bits sind für Version und Variante reserviert. Das ergibt 2¹²² mögliche Werte, also über 5 Quintillionen verschiedene UUIDs. crypto.randomUUID() generiert exakt dieses Format – die Methode wählt 122 zufällige Bits aus dem CSPRNG, setzt die vier Versionsbits auf 0100 und die zwei Variantenbits auf 10, und formatiert das Ergebnis als standardisierten UUID-String. Das Ergebnis ist vollständig RFC-4122-konform und interoperabel mit allen Systemen, die UUID v4 erwarten.


// crypto.randomUUID() — available in all modern browsers and Node.js 14.17+
const id = crypto.randomUUID();
// Example output: '550e8400-e29b-41d4-a716-446655440000'
// Format: xxxxxxxx-xxxx-4xxx-[89ab]xxx-xxxxxxxxxxxx

console.log(id.length);     // Always 36 characters
console.log(id[14]);        // Always '4' (version 4)
console.log('89ab'.includes(id[19])); // Always true (RFC 4122 variant)

// Verify UUID v4 format with regex
const UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
console.log(UUID_V4_REGEX.test(crypto.randomUUID())); // Always true

// Generate multiple UUIDs
const ids = Array.from({ length: 5 }, () => crypto.randomUUID());
// Every call produces a unique, cryptographically random ID

3. crypto.randomUUID() — die native Methode

crypto.randomUUID() ist eine synchrone Methode des globalen crypto-Objekts – kein Promise, kein Callback. Sie gibt direkt einen UUID-String zurück. Das ist ein bewusstes Design-Entscheid: UUID-Generierung aus einem CSPRNG ist so schnell (Mikrosekunden), dass Asynchronität keinen Vorteil bringt und den Code unnötig kompliziert machen würde. Die Methode ist seit Chrome 92, Firefox 95, Safari 15.4 und Node.js 14.17 verfügbar – mit nahezu vollständiger Browser-Abdeckung.

Ein wichtiges Detail zu crypto.randomUUID(): Wie andere Secure-Context-APIs ist sie in modernen Browsern nur auf HTTPS-Seiten und localhost verfügbar. Auf HTTP-Seiten ist crypto.randomUUID zwar möglicherweise vorhanden (das hängt vom Browser und der Konfiguration ab), aber der Secure-Context-Requirement der Web Crypto API legt nahe, immer den Sicherheitskontext zu prüfen. In Node.js und Deno ist crypto.randomUUID() ohne Einschränkungen verfügbar, da es kein Browser-Sicherheitsmodell gibt.

4. Wie crypto.randomUUID() intern funktioniert

Intern ruft crypto.randomUUID() den CSPRNG des Betriebssystems auf – unter Linux /dev/urandom, unter Windows BCryptGenRandom, unter macOS arc4random. Diese Quellen nutzen Hardware-Entropy-Quellen wie CPU-Timing-Jitter, Interrupt-Timing und (bei modernen CPUs) den Hardware-Zufallsgenerator über die RDRAND-Instruktion. Der resultierende Zufallsstrom ist kryptografisch sicher, was bedeutet, dass selbst bei Kenntnis aller bisher generierten UUIDs die nächste nicht vorhersagbar ist.

Die Implementierung in V8 (dem JavaScript-Engine in Chrome und Node.js) nutzt intern denselben Zufallsgenerator wie crypto.getRandomValues() – die niedrigstufige Methode der Web Crypto API. crypto.randomUUID() ist im Wesentlichen ein bequemer Wrapper, der 16 zufällige Bytes über getRandomValues holt, die Versions- und Variantenbits setzt und das Ergebnis als UUID-String formatiert. Wer eine eigene UUID-Implementierung verstehen will, kann das mit zwei Zeilen Code nachbauen – aber in der Praxis sollte man immer crypto.randomUUID() direkt verwenden, da es in der JavaScript-Engine optimiert ist.


// Understanding crypto.randomUUID() internals
// This manual implementation mirrors what the native method does

function manualUuidV4() {
  // Get 16 cryptographically random bytes
  const bytes = crypto.getRandomValues(new Uint8Array(16));

  // Set version bits (4 = 0100) at byte index 6
  bytes[6] = (bytes[6] & 0x0f) | 0x40;

  // Set variant bits (RFC 4122 = 10xx) at byte index 8
  bytes[8] = (bytes[8] & 0x3f) | 0x80;

  // Format as UUID string: 8-4-4-4-12
  const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}

// Always prefer the native method over manual implementation
const native = crypto.randomUUID();      // Optimized, maintained by browser
const manual = manualUuidV4();           // Equivalent result, but redundant

console.log(native);  // e.g. 'a2f8b3c4-e1d7-4f56-89ab-c3d2e1f09876'
console.log(manual);  // Same format, different random value

5. crypto.randomUUID() vs. Math.random()-Hacks

Vor crypto.randomUUID() kursierten im Web zahlreiche UUID-Implementierungen auf Basis von Math.random(). Das bekannteste Snippet ('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, fn)) erzeugt optisch korrekte UUIDs, verwendet aber Math.random() als Entropiequelle. Math.random() ist kein CSPRNG – in V8 nutzt es den xorshift128+-Algorithmus, der mit bekanntem internen Zustand vollständig vorhersagbar ist. Für UI-IDs ohne Sicherheitsbezug ist das akzeptabel. Für alles, was als geheimer Token, Nonce oder Session-ID dient, ist es gefährlich.

Der praktische Unterschied: Mit crypto.randomUUID() generierte IDs sind nicht durch Beobachtung mehrerer vergangener IDs vorhersagbar. Mit Math.random()-basierten IDs ist es theoretisch möglich, aus einer Sequenz von UUIDs den internen Zustand des PRNG zu rekonstruieren und zukünftige IDs vorherzusagen. In einem Angriffsszenario, wo ein Angreifer durch eine XSS-Lücke mehrere generierte IDs beobachten kann, wäre das ein reales Risiko. crypto.randomUUID() hat dieses Risiko strukturell eliminiert.

6. crypto.randomUUID() in Node.js

In Node.js steht crypto.randomUUID() seit Version 14.17.0 über das eingebaute crypto-Modul zur Verfügung. Seit Node.js 19 ist crypto auch als globales Objekt verfügbar (wie im Browser), sodass crypto.randomUUID() ohne Import aufgerufen werden kann. Für ältere Node.js-Versionen ist der Import erforderlich: const { randomUUID } = require('crypto') (CommonJS) oder import { randomUUID } from 'node:crypto' (ESM). Das node:-Präfix ist seit Node.js 14.18 verfügbar und explizit empfohlen, da es klar signalisiert, dass es sich um ein eingebautes Modul handelt, und Shadowing durch npm-Pakete mit gleichem Namen verhindert.

In verteilten Node.js-Anwendungen, wo viele Prozesse oder Pods gleichzeitig crypto.randomUUID() aufrufen, sind Kollisionen praktisch ausgeschlossen. Der UUID-v4-Raum mit 2¹²² möglichen Werten ist so groß, dass selbst bei einer Million UUIDs pro Sekunde aus tausend Pods die Kollisionswahrscheinlichkeit über einen Zeitraum von hundert Jahren astronomisch gering bleibt. Das macht crypto.randomUUID() zu einem zuverlässigen Primärschlüssel-Generator für clientseitig erstellte Datenbankeinträge ohne zentralen ID-Generator.


// Node.js: import crypto.randomUUID — prefer node: prefix
import { randomUUID } from 'node:crypto';

// Express route: generate idempotency token
app.post('/api/orders', async (req, res) => {
  const idempotencyKey = req.headers['idempotency-key'] ?? randomUUID();

  // Check if request was already processed
  const existing = await db.orders.findOne({ idempotencyKey });
  if (existing) {
    return res.status(200).json(existing);
  }

  const order = await db.orders.create({
    id: randomUUID(),          // Primary key — generated client-side
    idempotencyKey,
    ...req.body,
    createdAt: new Date(),
  });

  res.status(201).json(order);
});

// Batch ID generation — all unique, no collision risk
const batchIds = Array.from({ length: 1000 }, randomUUID);

// Correlation ID for distributed tracing
function createRequestContext() {
  return {
    requestId: randomUUID(),
    traceId: randomUUID(),
    spanId: randomUUID().replace(/-/g, '').slice(0, 16), // 16-char span ID
  };
}

7. Praxisanwendungen: IDs, Tokens und Deduplikation

crypto.randomUUID() löst mehrere konkrete Probleme in der Webentwicklung. Erstens: temporäre IDs für optimistisches UI-Rendering. Wenn ein Nutzer ein Formular absendet, möchte man die neue Entität sofort in der UI anzeigen, bevor die Server-Antwort eintrifft. Dafür braucht man eine ID, die clientseitig generiert werden kann und mit der Server-ID übereinstimmt – oder durch sie ersetzt wird. Zweitens: Idempotenz-Tokens für API-Requests. Bei HTTP-Requests, die nicht idempotent sind (POST, PATCH), sendet man einen einmaligen Token im Header, den der Server zur Duplikaterkennung nutzt.

Drittens: Request-Deduplikation in Offline-First-Apps. Wenn ein Nutzer eine Aktion ausführt, die offline gespeichert und später synchronisiert wird, braucht jede Aktion eine eindeutige ID, damit der Server doppelte Synchronisierungen erkennt. crypto.randomUUID() ist dafür ideal: schnell genug, um synchron im Event-Handler aufgerufen zu werden, sicher genug, dass keine Kollisionen mit parallel arbeitenden anderen Clients auftreten. Viertens: Correlation-IDs für Frontend-Logging. Jeder API-Request erhält eine eindeutige ID, die im Frontend-Log und im Server-Log erscheint und das Debugging in verteilten Systemen ermöglicht.

8. Kollisionswahrscheinlichkeit und Skalierung

Die Kollisionswahrscheinlichkeit von crypto.randomUUID() basiert auf dem Geburtstagsparadoxon: Bei n generierten UUIDs aus einem Raum von 2¹²² möglichen Werten beträgt die Wahrscheinlichkeit einer Kollision ungefähr n²/(2 × 2¹²²). Konkret: um eine 50%ige Kollisionswahrscheinlichkeit zu erreichen, müsste man etwa 2,7 × 10¹⁸ UUIDs generieren – das sind 2,7 Milliarden Milliarden. Eine Anwendung, die eine Million UUIDs pro Sekunde generiert, würde dafür 85 Millionen Jahre benötigen. In der Praxis ist die Kollisionswahrscheinlichkeit bei allen realistischen Anwendungsfällen vernachlässigbar.

Dennoch gibt es Szenarien, in denen UUID v4 durch spezialisiertere Formate ergänzt werden sollte. Sortierbarkeit ist ein häufiges Anforderungsmerkmal in Datenbanken: UUID v4 hat keine inhärente zeitliche Ordnung, was bei großen Datensätzen zu B-Tree-Fragmentierung führen kann. Formate wie ULID (Universally Unique Lexicographically Sortable Identifier) oder UUID v7 (das einen Zeitstempel als Präfix enthält) lösen dieses Problem. Für diese Formate gibt es keine native Browser-API – hier braucht man tatsächlich eine externe Library. crypto.randomUUID() ist die richtige Wahl, wenn Sortierbarkeit keine Anforderung ist.

Methode Sicherheit Sortierbar Abhängigkeit
crypto.randomUUID() CSPRNG – sehr hoch Nein (zufällig) Keine (nativ)
Math.random() UUID-Hack PRNG – vorhersagbar Nein Keine
uuid npm (v4) CSPRNG intern Nein npm-Paket nötig
ULID CSPRNG intern Ja (Zeit-Präfix) npm-Paket nötig
UUID v7 CSPRNG intern Ja (Zeit-Präfix) npm-Paket nötig

9. crypto.randomUUID() vs. UUID-Libraries im Vergleich

Das npm-Paket uuid (über 80 Millionen Downloads pro Woche) war lange der Standard für UUID-Generierung in JavaScript. Seit crypto.randomUUID() nativ verfügbar ist, wird es für den reinen UUID-v4-Anwendungsfall redundant. Der Unterschied liegt in der Abhängigkeitsgröße (das uuid-Paket ist minimal, aber nicht null), der Kompatibilität (uuid unterstützt auch UUID v1, v3, v5) und der Handhabung älterer Umgebungen. Wenn das Projekt bereits Node.js 14.17+ und moderne Browser voraussetzt, ist crypto.randomUUID() die bessere Wahl: keine externe Abhängigkeit, keine Package-Vulnerabilities, keine Versionskonflikt.

Für Teams, die Sortierbarkeit benötigen oder andere UUID-Versionen (v1 für zeitbasierte IDs, v5 für namensbasierte deterministische IDs) verwenden, bleibt die uuid-Library oder spezialisierte Alternativen wie ulid oder nanoid sinnvoll. nanoid ist eine besonders interessante Alternative zu crypto.randomUUID(): es nutzt ebenfalls den CSPRNG, generiert aber kürzere, URL-sichere IDs, die in URLs, Dateinamen und Anzeige kompakter sind. Die Wahl zwischen crypto.randomUUID() und nanoid hängt davon ab, ob RFC-4122-Konformität eine Anforderung ist.

Mironsoft

Sichere JavaScript-Architekturen und moderne Web-APIs

Sicherheitslücken durch Math.random() in Ihrer App?

Wir auditieren bestehenden Code auf unsichere Zufallsgeneratoren und migrieren auf crypto.randomUUID() und die Web Crypto API – für IDs, Tokens und Nonces, die echten kryptografischen Standards genügen.

Security Audit

Math.random()-Verwendungen identifizieren und Risikopotenzial bewerten

Migration

Sichere Replacement durch crypto.randomUUID() und getRandomValues()

Architektur

ID-Strategien für verteilte Systeme: UUID v4, ULID oder UUID v7

10. Zusammenfassung

crypto.randomUUID() ist die einfachste und sicherste Methode, UUID v4 in modernem JavaScript zu generieren – ohne externe Abhängigkeiten, ohne Boilerplate, ohne Sicherheitskompromisse. Die Methode ist synchron, liefert garantiert RFC-4122-konforme UUIDs aus einem kryptografisch sicheren Zufallsgenerator und ist in Browser und Node.js gleichermaßen verfügbar. Für alle Anwendungsfälle, in denen UUID v4 ausreicht – temporäre IDs, Idempotenz-Tokens, Correlation-IDs, optimistisches UI-Rendering – ist crypto.randomUUID() die richtige Wahl.

Die Entscheidung für externe Libraries wie uuid, ulid oder nanoid ist berechtigt, wenn spezifische Anforderungen bestehen: Sortierbarkeit (ULID, UUID v7), kürzere IDs (nanoid), andere UUID-Versionen (v1, v3, v5 über uuid) oder Kompatibilität mit sehr alten Browser-Versionen. In allen anderen Fällen ist crypto.randomUUID() die überlegene Wahl: eine Zeile Code, keine Abhängigkeiten, maximale Sicherheit. Das Math.random()-UUID-Snippet, das seit zehn Jahren durch Stack-Overflow-Antworten kopiert wird, hat damit keinen Platz mehr in neuem Code.

crypto.randomUUID() — Das Wichtigste auf einen Blick

Verfügbarkeit

Chrome 92+, Firefox 95+, Safari 15.4+, Node.js 14.17+. In Node.js: import { randomUUID } from 'node:crypto'.

Sicherheit

CSPRNG des Betriebssystems. Nicht vorhersagbar, nicht aus vergangenen Werten ableitbar. Ersetzt Math.random()-basierte UUID-Hacks vollständig.

Format

RFC-4122-konform. 36 Zeichen, 32 Hex + 4 Bindestriche. Versionsbyte: immer 4. Variantbyte: immer 8, 9, a oder b.

Wann externe Library?

Bei Sortierbarkeit (ULID/UUID v7), kürzeren IDs (nanoid) oder anderen UUID-Versionen (uuid-npm). Sonst immer crypto.randomUUID().

11. FAQ: JavaScript crypto.randomUUID()

1Was ist crypto.randomUUID()?
Native Methode für UUID v4 aus dem CSPRNG des Betriebssystems. Keine externe Abhängigkeit. Browser und Node.js.
2Warum ist Math.random() für UUIDs unsicher?
xorshift128+ in V8 – deterministisch und vorhersagbar. Bei bekanntem internen Zustand lassen sich zukünftige Werte berechnen.
3UUID v4 vs. UUID v7?
v4: 122 zufällige Bits, nicht sortierbar. v7: Zeitstempel-Präfix, sortierbar, besser für DB-Indizes. Kein natives v7 in JavaScript.
4Node.js: wie importieren?
import { randomUUID } from 'node:crypto' (ESM) oder const { randomUUID } = require('crypto'). Ab Node.js 19 global verfügbar.
5Kann eine Kollision auftreten?
Theoretisch ja. 2¹²² mögliche Werte. Bei einer Million UUIDs/Sekunde dauert eine 50%ige Kollisionswahrscheinlichkeit 85 Millionen Jahre.
6Noch uuid npm nötig?
Für UUID v4 in modernen Umgebungen nicht. Nützlich für v1, v3, v5 oder alte Browser-Kompatibilität.
7Auf HTTP-Seiten verfügbar?
Web Crypto API erfordert HTTPS oder localhost. Node.js ohne Einschränkung.
8Synchron oder asynchron?
Synchron – gibt direkt einen String zurück. Kein Promise, kein await nötig.
9Unterschied zu nanoid?
Beide CSPRNG. crypto.randomUUID(): RFC-4122-konform, 36 Zeichen. nanoid: URL-sicher, 21 Zeichen, kein Standard-Format.
10UUID v4 validieren?
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i – prüft Format, Versionsbyte und Variantbyte.