CUID2 Generator
Generate secure next-generation CUID2 identifiers
Vygenerovaná CUID2
Co je CUID2?
CUID2 je druhá generace CUID, přepsaná od základů se zaměřením na kryptografickou bezpečnost a soukromí.
Na rozdíl od CUID v1, který viditelně vkládá časové razítko, CUID2 skrývá všechny komponenty uvnitř SHA3 hashe, čímž vytváří prakticky nepředvídatelné řetězce.
ID začíná přizpůsobitelným abecedním prefixem (výchozí c) následovaným base36 řetězcem SHA3 hashe.
Proč CUID2?
CUID2 vznikl jako odpověď na konkrétní bezpečnostní obavy v CUID v1:
- Odhalené časové razítko: CUID v1 odhaloval čas vytvoření na začátku každého ID.
- Předvídatelnost: Se znalostí struktury CUID v1 bylo možné odvodit část vnitřního stavu.
- Nedostatek kryptografické bezpečnosti: CUID v1 explicitně nepoužíval kryptograficky bezpečný generátor náhodných čísel.
CUID2 tyto obavy řeší použitím SHA3, CSPRNG a skrytím časového razítka.
Principy návrhu
CUID2 vs CUID v1
Porovnání klíčových charakteristik mezi oběma generacemi:
| Atribut | CUID2 | CUID v1 |
|---|---|---|
| Bezpečnost | Kryptografická (SHA3+CSPRNG) | Nekryptografická |
| Předvídatelnost | Velmi nízká | Nízká (odhalené časové razítko) |
| Délka | Přizpůsobitelná (výchozí 24) | Pevných 25 znaků |
| Prefix | Přizpůsobitelný | Pevné 'c' |
| Distribuce | Rovnoměrně distribuovaná | Vychýlená k časovému razítku |
| Stav | Aktivní a doporučený | Zastaralý |
CUID2 vs UUID v4
Porovnání s běžným standardem UUID:
| Atribut | CUID2 | UUID v4 |
|---|---|---|
| Výchozí délka | 24 znaků | 36 znaků |
| Bezpečný pro URL | Ano | Ano (s pomlčkami) |
| Vlastní délka | Ano | Ne |
| Tříditelný | Ne | Ne |
| Entropie | Vysoká (SHA3) | Vysoká (CSPRNG) |
| Sada znaků | Malá alfanumerická písmena | Hex + pomlčky |
CUID2 poskytuje zaručený abecední prefix a flexibilní délku se srovnatelnou bezpečností jako UUID v4.
Kdo používá CUID2?
CUID2 byl přijat prominentními komunitami a frameworky:
- Prisma podporuje CUID2 jako typ ID v poli
@idprostřednictvím@default(cuid()). - Komunita Drizzle ORM přijala CUID2 pro výchozí ID.
- Projekty SvelteKit a Remix jej používají pro ID relací.
- Vysoce zatížené API servery, které potřebují sledovatelná ID v logách.
- Aplikace synchronizující data přes více databází nebo regionů.
Příklady kódu
Instalace a použití: pnpm add @paralleldrive/cuid2
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"Pokročilá konfigurace:
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Integrace s databází:
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"