Generatore CUID2
Genera identificatori CUID2 sicuri di nuova generazione
CUID2 generati
Cos'è CUID2?
CUID2 (Collision-resistant Unique ID, versione 2) è il successore di nuova generazione di CUID v1, progettato per generare ID brevi, crittograficamente sicuri e opachi che sono sicuri da usare come chiavi primarie in database, URL e sistemi distribuiti.
A differenza del suo predecessore, CUID2 non rivela alcuna informazione sul momento della creazione, la macchina host o il processo che l'ha generato. Ogni ID è una stringa apparentemente casuale che inizia con una lettera minuscola casuale seguita da un hash base-36 derivato da SHA-512. La lunghezza predefinita è 24 caratteri, ma puoi configurarla da 2 a 32 caratteri in base alle tue esigenze di archiviazione.
CUID2 è ampiamente raccomandato dai toolkit di database moderni. Prisma lo ha adottato come strategia ID predefinita per il suo scalare @default(cuid()), e PlanetScale, Neon e altri provider di database serverless elencano esplicitamente CUID2 come formato ID preferito.
Perché CUID2 Ha Sostituito CUID v1
CUID v1, rilasciato nel 2012 da Eric Elliott, era un importante miglioramento rispetto agli UUID semplici per la generazione di ID lato client. Tuttavia, i ricercatori di sicurezza hanno scoperto due problemi fondamentali nel suo design:
- Fingerprinting: L'impronta digitale dell'host incorporata in ogni valore CUID v1 poteva essere usata per identificare la macchina o il processo che ha generato l'ID, rivelando metadati operativi a chiunque potesse osservare gli ID.
- Prevedibilità: Poiché CUID v1 incorporava un contatore monotonicamente crescente e un segmento timestamp, un attaccante che osservava diversi ID poteva prevedere l'intervallo approssimativo dei futuri ID, abilitando attacchi di enumerazione contro API che usano gli ID come unico controllo di autorizzazione.
- Hash non crittografico: CUID v1 usava un semplice passaggio di hash non crittografico che non soddisfaceva gli standard di sicurezza moderni.
Eric Elliott, l'autore originale, ha formalmente deprecato CUID v1 e creato CUID2 da zero per risolvere tutti questi problemi. Il nuovo algoritmo usa la Web Crypto API (SHA-512) ed elimina tutti i componenti deterministici.
Principi di Design di CUID2
CUID2 vs CUID v1 — Confronto
La tabella seguente riassume le differenze chiave tra CUID2 e il now deprecato CUID v1. Se stai attualmente usando CUID v1, è fortemente raccomandato migrare a CUID2.
| Attributo | CUID2 | CUID v1 |
|---|---|---|
| Sicurezza | Crittografico (SHA-512) | Non crittografico (basato su impronta digitale) |
| Prevedibilità | Opaco — nessun metadato rivelato | Timestamp + impronta digitale visibili nell'ID |
| Lunghezza | Configurabile (2–32 chars) | Fisso 25 chars |
| Prefisso | Lettera casuale a–z | Inizia sempre con "c" |
| Distribuzione | Piatta / uniforme | Segmenti monotonicamente crescenti |
| Stato | Attivamente mantenuto | Deprecato dall'autore originale |
CUID2 vs UUID v4 — Confronto
UUID v4 è lo standard dominante per ID unici casuali. CUID2 offre diversi vantaggi pratici rispetto a UUID v4 senza sacrificare la sicurezza.
| Attributo | CUID2 | UUID v4 |
|---|---|---|
| Lunghezza predefinita | 24 caratteri | 36 caratteri (con trattini) |
| Sicuro per URL | Sì — minuscole a–z + 0–9 | Richiede codifica (contiene trattini) |
| Lunghezza personalizzata | Sì (2–32) | No — sempre 128 bit / 36 chars |
| Ordinabile | No (by design) | No (v4 è casuale) |
| Fonte di entropia | SHA-512 + Web Crypto | CSPRNG |
| Set di caratteri | Base-36 (a–z, 0–9) | Hex + trattini |
Il principale compromesso è la familiarità: UUID v4 è uno standard IETF (RFC 4122) riconosciuto da praticamente ogni database, linguaggio di programmazione e framework API. CUID2 è uno standard della comunità con supporto crescente ma non universale. Scegli UUID v4 quando l'interoperabilità con sistemi esterni è fondamentale; scegli CUID2 quando controlli entrambe le estremità e preferisci ID più corti e sicuri per URL.
Chi Usa CUID2
CUID2 ha visto una rapida adozione nell'ecosistema moderno di JavaScript e TypeScript:
- Prisma — il più popolare TypeScript ORM usa CUID2 come predefinito raccomandato per i campi
@idcon@default(cuid())in Prisma Schema v2+. - PlanetScale — la loro documentazione e i modelli di avvio raccomandano CUID2 per le chiavi primarie generate dall'applicazione per evitare problemi di performance di scansione sequenziale sulla loro piattaforma MySQL distribuita.
- Drizzle ORM — fornisce un helper predefinito integrato
cuid2()per le definizioni di colonne. - Boilerplate tRPC — molti template comunitari tRPC + Prisma vengono forniti con CUID2 come strategia di chiave primaria.
- T3 Stack — lo strumento di scaffolding create-t3-app usa Prisma con valori predefiniti CUID2 nei file di schema generati.
Esempi di Codice
Il pacchetto npm ufficiale @paralleldrive/cuid2 fornisce una semplice 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"Usando CUID2 con lo schema Prisma:
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Generare CUID2 in Node.js senza il pacchetto npm (usando solo la Web Crypto API, come fa questo strumento nel 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"