Gerador CUID2
Gera identificadores CUID2 seguros de próxima geração
CUID2s gerados
O que é CUID2?
CUID2 (ID Único Resistente a Colisões, versão 2) é o sucessor de nova geração do CUID v1, projetado para gerar IDs curtos, criptograficamente seguros e opacos que são seguros para usar como chaves primárias em bancos de dados, URLs e sistemas distribuídos.
Ao contrário de seu predecessor, CUID2 não revela informações sobre o momento de criação, a máquina host ou o processo que o gerou. Cada ID é uma string aparentemente aleatória que começa com uma letra minúscula aleatória seguida de um hash base-36 derivado de SHA-512. O comprimento padrão é 24 caracteres, mas você pode configurá-lo entre 2 e 32 caracteres conforme suas restrições de armazenamento.
CUID2 é amplamente recomendado pelos kits de ferramentas de banco de dados modernos. Prisma o adotou como estratégia de ID padrão para seu escalar @default(cuid()), e PlanetScale, Neon e outros provedores de banco de dados serverless listam explicitamente CUID2 como formato de ID preferido porque evita as vulnerabilidades de varredura sequencial de inteiros autoincrement enquanto é mais curto e legível do que um UUID.
Por que CUID2 Substituiu CUID v1
CUID v1, lançado em 2012 por Eric Elliott, foi uma melhoria significativa sobre UUIDs simples para geração de IDs no lado do cliente. No entanto, pesquisadores de segurança descobriram dois problemas fundamentais com seu design:
- Fingerprinting: A impressão digital do host incorporada em cada valor CUID v1 poderia ser usada para identificar a máquina ou processo que gerou o ID, vazando metadados operacionais para qualquer pessoa que pudesse observar os IDs.
- Previsibilidade: Como CUID v1 incorporava um contador monotonicamente crescente e um segmento de timestamp, um atacante que observasse vários IDs poderia prever o intervalo aproximado de IDs futuros, habilitando ataques de enumeração contra APIs que usam IDs como único controle de autorização.
- Hash não criptográfico: CUID v1 usava um passo de hash não criptográfico simples que não atendia aos padrões de segurança modernos.
Eric Elliott, o autor original, formalmente deprecou CUID v1 e criou CUID2 do zero para resolver todos esses problemas. O novo algoritmo usa a Web Crypto API (SHA-512) e elimina todos os componentes determinísticos, tornando cada ID estatisticamente independente de todos os outros.
Princípios de Design do CUID2
CUID2 vs CUID v1 — Comparação
A tabela abaixo resume as principais diferenças entre CUID2 e o agora obsoleto CUID v1. Se você atualmente usa CUID v1, migrar para CUID2 é fortemente recomendado.
| Atributo | CUID2 | CUID v1 |
|---|---|---|
| Segurança | Criptográfico (SHA-512) | Não criptográfico (baseado em impressão digital) |
| Previsibilidade | Opaco — sem metadados vazados | Timestamp + impressão digital visíveis no ID |
| Comprimento | Configurável (2–32 chars) | Fixo 25 chars |
| Prefixo | Letra aleatória a–z | Sempre começa com "c" |
| Distribuição | Plana / uniforme | Segmentos monotonicamente crescentes |
| Status | Ativamente mantido | Deprecado pelo autor original |
CUID2 vs UUID v4 — Comparação
UUID v4 é o padrão dominante para IDs únicos aleatórios. CUID2 oferece várias vantagens práticas sobre UUID v4 sem sacrificar segurança.
| Atributo | CUID2 | UUID v4 |
|---|---|---|
| Comprimento padrão | 24 caracteres | 36 caracteres (com hífens) |
| Seguro para URL | Sim — minúsculas a–z + 0–9 | Requer codificação (contém hífens) |
| Comprimento personalizado | Sim (2–32) | Não — sempre 128 bits / 36 chars |
| Ordenável | Não (por design) | Não (v4 é aleatório) |
| Fonte de entropia | SHA-512 + Web Crypto | CSPRNG |
| Conjunto de caracteres | Base-36 (a–z, 0–9) | Hex + hífens |
O principal compromisso é a familiaridade: UUID v4 é um padrão IETF (RFC 4122) reconhecido por praticamente todos os bancos de dados, linguagens de programação e frameworks de API. CUID2 é um padrão comunitário com suporte crescente mas não universal. Escolha UUID v4 quando a interoperabilidade com sistemas externos é primordial; escolha CUID2 quando você controla ambos os extremos e prefere IDs mais curtos e seguros para URL.
Quem Usa CUID2
CUID2 tem visto adoção rápida em todo o ecossistema moderno de JavaScript e TypeScript:
- Prisma — o ORM de TypeScript mais popular usa CUID2 como padrão recomendado para campos
@idcom@default(cuid())no Prisma Schema v2+. - PlanetScale — sua documentação e modelos iniciais recomendam CUID2 para chaves primárias geradas pela aplicação para evitar problemas de desempenho de varredura sequencial em sua plataforma MySQL distribuída.
- Drizzle ORM — fornece um helper padrão integrado
cuid2()para definições de colunas. - Modelos tRPC — muitos modelos comunitários de tRPC + Prisma vêm com CUID2 como estratégia de chave primária.
- T3 Stack — a ferramenta de scaffolding create-t3-app usa Prisma com padrões CUID2 nos arquivos de esquema gerados.
Exemplos de Código
O pacote oficial npm @paralleldrive/cuid2 fornece uma API simples:
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 com o esquema do Prisma:
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Gerando CUID2 no Node.js sem o pacote npm (usando apenas a Web Crypto API, como esta ferramenta faz no navegador):
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"