CUID2 Generator
Generate secure next-generation CUID2 identifiers
Generierte CUID2s
Was ist CUID2?
CUID2 (Collision-resistant Unique ID, Version 2) ist der Nachfolger der nächsten Generation von CUID v1, der entwickelt wurde, um kurze, kryptografisch sichere, opake IDs zu generieren, die als Primärschlüssel in Datenbanken, URLs und verteilten Systemen sicher verwendet werden können.
Im Gegensatz zu seinem Vorgänger verrät CUID2 keine Informationen über den Erstellungszeitpunkt, die Host-Maschine oder den Prozess, der es generiert hat. Jede ID ist eine scheinbar zufällige Zeichenfolge, die mit einem zufälligen Kleinbuchstaben beginnt, gefolgt von einem base-36-Hash aus SHA-512. Die Standardlänge beträgt 24 Zeichen, kann aber von 2 bis 32 Zeichen konfiguriert werden.
CUID2 wird von modernen Datenbank-Toolkits weitgehend empfohlen. Prisma hat es als Standard-ID-Strategie für seinen @default(cuid())-Skalar übernommen, und PlanetScale, Neon sowie andere serverlose Datenbankprovider listen CUID2 explizit als bevorzugtes ID-Format auf.
Warum CUID2 CUID v1 Ersetzt Hat
CUID v1, das 2012 von Eric Elliott veröffentlicht wurde, war eine wichtige Verbesserung gegenüber einfachen UUIDs für die clientseitige ID-Generierung. Sicherheitsforscher entdeckten jedoch zwei grundlegende Probleme mit seinem Design:
- Fingerprinting: Der in jeden CUID v1-Wert eingebettete Host-Fingerabdruck konnte verwendet werden, um die Maschine oder den Prozess zu identifizieren, der die ID generiert hat, was operative Metadaten an jeden preisgab, der die IDs beobachten konnte.
- Vorhersagbarkeit: Da CUID v1 einen monoton steigenden Zähler und ein Zeitstempel-Segment enthielt, konnte ein Angreifer, der mehrere IDs beobachtete, den ungefähren Bereich zukünftiger IDs vorhersagen, was Enumerationsangriffe gegen APIs ermöglicht, die IDs als einzige Autorisierungsprüfung verwenden.
- Nicht-kryptografischer Hash: CUID v1 verwendete einen einfachen nicht-kryptografischen Hash-Schritt, der modernen Sicherheitsstandards nicht entsprach.
Eric Elliott, der ursprüngliche Autor, hat CUID v1 formal als veraltet erklärt und CUID2 von Grund auf neu entwickelt, um all diese Probleme zu beheben. Der neue Algorithmus verwendet die Web Crypto API (SHA-512) und eliminiert alle deterministischen Komponenten.
CUID2 Design-Prinzipien
CUID2 vs CUID v1 — Vergleich
Die folgende Tabelle fasst die wichtigsten Unterschiede zwischen CUID2 und dem nun veralteten CUID v1 zusammen. Wenn Sie derzeit CUID v1 verwenden, wird die Migration zu CUID2 dringend empfohlen.
| Attribut | CUID2 | CUID v1 |
|---|---|---|
| Sicherheit | Kryptografisch (SHA-512) | Nicht-kryptografisch (fingerabdruckbasiert) |
| Vorhersagbarkeit | Opak — keine Metadaten preisgegeben | Zeitstempel + Fingerabdruck in ID sichtbar |
| Länge | Konfigurierbar (2–32 Zeichen) | Fest 25 Zeichen |
| Präfix | Zufälliger Buchstabe a–z | Beginnt immer mit "c" |
| Verteilung | Flach / gleichmäßig | Monoton steigende Segmente |
| Status | Aktiv gepflegt | Vom ursprünglichen Autor als veraltet markiert |
CUID2 vs UUID v4 — Vergleich
UUID v4 ist der dominierende Standard für zufällige eindeutige IDs. CUID2 bietet gegenüber UUID v4 mehrere praktische Vorteile ohne Sicherheitseinbußen.
| Attribut | CUID2 | UUID v4 |
|---|---|---|
| Standardlänge | 24 Zeichen | 36 Zeichen (mit Bindestrichen) |
| URL-sicher | Ja — Kleinbuchstaben a–z + 0–9 | Erfordert Kodierung (enthält Bindestriche) |
| Benutzerdefinierte Länge | Ja (2–32) | Nein — immer 128 Bits / 36 Zeichen |
| Sortierbar | Nein (by design) | Nein (v4 ist zufällig) |
| Entropiequelle | SHA-512 + Web Crypto | CSPRNG |
| Zeichensatz | Base-36 (a–z, 0–9) | Hex + Bindestriche |
Der wichtigste Kompromiss ist die Vertrautheit: UUID v4 ist ein IETF-Standard (RFC 4122), der von nahezu jeder Datenbank, Programmiersprache und jedem API-Framework unterstützt wird. CUID2 ist ein Community-Standard mit wachsender, aber nicht universeller Unterstützung. Wählen Sie UUID v4, wenn Interoperabilität mit externen Systemen entscheidend ist; wählen Sie CUID2, wenn Sie beide Seiten kontrollieren und kürzere, URL-sichere IDs bevorzugen.
Wer Verwendet CUID2
CUID2 hat im modernen JavaScript- und TypeScript-Ökosystem schnell an Verbreitung gewonnen:
- Prisma — das beliebteste TypeScript ORM verwendet CUID2 als empfohlenen Standard für
@id-Felder mit@default(cuid())in Prisma Schema v2+. - PlanetScale — ihre Dokumentation und Starter-Vorlagen empfehlen CUID2 für anwendungsgenerierte Primärschlüssel, um sequentielle Scan-Performance-Probleme auf ihrer verteilten MySQL-Plattform zu vermeiden.
- Drizzle ORM — bietet einen eingebauten Standard-Helper
cuid2()für Spaltendefinitionen. - tRPC-Boilerplates — viele Community-tRPC + Prisma-Starter-Vorlagen werden mit CUID2 als Primärschlüssel-Strategie geliefert.
- T3 Stack — das create-t3-app-Scaffolding-Tool verwendet Prisma mit CUID2-Standards in generierten Schema-Dateien.
Code-Beispiele
Das offizielle npm-Paket @paralleldrive/cuid2 bietet eine einfache API:
import { createId } from '@paralleldrive/cuid2'
// Generate a single CUID2 (default length: 24)
const id = createId()
console.log(id) // e.g. "tz4a98xxat96iws9zmbrgj3a"
// Custom length
import { init } from '@paralleldrive/cuid2'
const createShortId = init({ length: 16 })
const shortId = createShortId()
console.log(shortId) // e.g. "tz4a98xxat96iws9"Verwendung von CUID2 mit dem Prisma-Schema:
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Generierung von CUID2 in Node.js ohne das npm-Paket (nur mit der Web Crypto API, wie dieses Tool im Browser):
async function generateCuid2(length = 24) {
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
// Random prefix letter
const firstByte = crypto.getRandomValues(new Uint8Array(1))[0]
const firstChar = alphabet[firstByte % 26]
// Random 32-byte salt
const salt = crypto.getRandomValues(new Uint8Array(32))
const saltHex = [...salt].map(b => b.toString(16).padStart(2, '0')).join('')
// SHA-512 of timestamp + salt
const input = Date.now().toString(36) + saltHex
const hashBuffer = await crypto.subtle.digest(
'SHA-512',
new TextEncoder().encode(input)
)
// Encode hash bytes as base-36 string
const bytes = new Uint8Array(hashBuffer)
let hash = ''
for (let i = 0; i < bytes.length; i += 8) {
let chunk = 0n
for (let j = 0; j < 8 && i + j < bytes.length; j++) {
chunk = (chunk << 8n) | BigInt(bytes[i + j])
}
hash += chunk.toString(36)
}
return (firstChar + hash).slice(0, length)
}
// Usage
const id = await generateCuid2()
console.log(id) // e.g. "m7k3r9p2nxq8zt5a6cwj4bvd"