CUID2 Generator
Generate secure next-generation CUID2 identifiers
Згенеровані CUID2
Що таке CUID2?
CUID2 — це друге покоління CUID, переписане з нуля з акцентом на криптографічну безпеку та конфіденційність.
На відміну від CUID v1, який видимо вбудовує мітку часу, CUID2 приховує всі компоненти в хеші SHA3, створюючи практично непередбачувані рядки.
ID починаються з налаштовуваного буквеного префікса (за замовчуванням c), за яким іде рядок base36 з хешу SHA3.
Чому CUID2?
CUID2 з'явився у відповідь на конкретні проблеми безпеки в CUID v1:
- Відкрита мітка часу: CUID v1 розкривав час створення на початку кожного ID.
- Передбачуваність: Знаючи структуру CUID v1, можна було вивести частину внутрішнього стану.
- Відсутність криптографічної безпеки: CUID v1 явно не використовував криптографічно безпечний генератор випадкових чисел.
CUID2 вирішує ці проблеми, використовуючи SHA3, CSPRNG та приховування мітки часу.
Принципи проектування
CUID2 проти CUID v1
Порівняння ключових характеристик між двома поколіннями:
| Атрибут | CUID2 | CUID v1 |
|---|---|---|
| Безпека | Криптографічна (SHA3+CSPRNG) | Некриптографічна |
| Передбачуваність | Дуже низька | Низька (відкрита мітка часу) |
| Довжина | Налаштовувана (за замовчуванням 24) | Фіксована 25 символів |
| Префікс | Налаштовуваний | Фіксований 'c' |
| Розподіл | Рівномірно розподілений | Зміщений до мітки часу |
| Статус | Активний та рекомендований | Застарілий |
CUID2 проти UUID v4
Порівняння зі звичайним стандартом UUID:
| Атрибут | CUID2 | UUID v4 |
|---|---|---|
| Довжина за замовчуванням | 24 символи | 36 символів |
| Безпечний для URL | Так | Так (з дефісами) |
| Власна довжина | Так | Ні |
| Сортування | Ні | Ні |
| Ентропія | Висока (SHA3) | Висока (CSPRNG) |
| Набір символів | Рядкові буквено-цифрові символи | Hex + дефіси |
CUID2 забезпечує гарантований буквений префікс та гнучку довжину з безпекою, еквівалентною UUID v4.
Хто використовує CUID2?
CUID2 прийнятий видатними спільнотами та фреймворками:
- Prisma підтримує CUID2 як тип ID у полі
@idчерез@default(cuid()). - Спільнота Drizzle ORM використовує CUID2 для ID за замовчуванням.
- Проекти SvelteKit та Remix використовують його для ідентифікаторів сесій.
- Високонавантажені API-сервери, яким потрібні відстежувані ID у журналах.
- Застосунки, що синхронізують дані між кількома базами даних або регіонами.
Приклади коду
Встановлення та використання: 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"Розширена конфігурація:
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Інтеграція з базою даних:
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"