Trình tạo CUID2
Tạo định danh CUID2 thế hệ tiếp theo an toàn
CUID2 đã tạo
CUID2 là gì?
CUID2 là thế hệ thứ hai của CUID, được viết lại từ đầu với trọng tâm là bảo mật mật mã và quyền riêng tư.
Không giống CUID v1 nhúng timestamp một cách hiển thị, CUID2 ẩn tất cả các thành phần trong hash SHA3, tạo ra các chuỗi thực tế không thể dự đoán.
Các ID bắt đầu bằng tiền tố chữ cái có thể tùy chỉnh (mặc định c) theo sau là chuỗi base36 của hash SHA3.
Tại Sao CUID2?
CUID2 ra đời để đáp lại các lo ngại bảo mật cụ thể trong CUID v1:
- Timestamp bị lộ: CUID v1 tiết lộ thời gian tạo ở đầu mỗi ID.
- Tính dự đoán: Với kiến thức về cấu trúc CUID v1, một phần trạng thái nội bộ có thể được suy ra.
- Thiếu bảo mật mật mã: CUID v1 không rõ ràng sử dụng bộ tạo số ngẫu nhiên an toàn mật mã.
CUID2 giải quyết những lo ngại này bằng cách sử dụng SHA3, CSPRNG và ẩn timestamp.
Nguyên Tắc Thiết Kế
CUID2 so với CUID v1
So sánh các đặc điểm chính giữa hai thế hệ:
| Thuộc tính | CUID2 | CUID v1 |
|---|---|---|
| Bảo mật | Mật mã (SHA3+CSPRNG) | Không mật mã |
| Tính Dự Đoán | Rất thấp | Thấp (timestamp bị lộ) |
| Độ dài | Tùy chỉnh (mặc định 24) | Cố định 25 ký tự |
| Tiền tố | Tùy chỉnh | Cố định 'c' |
| Phân phối | Phân phối đều | Lệch timestamp |
| Trạng thái | Hoạt động & được khuyến nghị | Đã lỗi thời |
CUID2 so với UUID v4
So sánh với tiêu chuẩn UUID phổ biến:
| Thuộc tính | CUID2 | UUID v4 |
|---|---|---|
| Độ Dài Mặc Định | 24 ký tự | 36 ký tự |
| An Toàn URL | Có | Có (với dấu gạch ngang) |
| Độ Dài Tùy Chỉnh | Có | Không |
| Có Thể Sắp Xếp | Không | Không |
| Entropy | Cao (SHA3) | Cao (CSPRNG) |
| Bộ Ký Tự | Chữ thường alphanumeric | Hex + dấu gạch ngang |
CUID2 cung cấp tiền tố chữ cái được đảm bảo và độ dài linh hoạt với bảo mật tương đương UUID v4.
Ai Sử Dụng CUID2?
CUID2 đã được các cộng đồng và framework nổi tiếng áp dụng:
- Prisma hỗ trợ CUID2 như một loại ID trong trường
@idqua@default(cuid()). - Cộng đồng Drizzle ORM áp dụng CUID2 cho ID mặc định.
- Các dự án SvelteKit và Remix sử dụng nó cho ID session.
- Máy chủ API khối lượng cao cần ID có thể theo dõi trong nhật ký.
- Các ứng dụng đồng bộ trên nhiều cơ sở dữ liệu hoặc vùng.
Ví Dụ Mã
Cài đặt và sử dụng: 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"Cấu hình nâng cao:
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Tích hợp cơ sở dữ liệu:
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"