CUID2 چیست؟
CUID2 (شناسه یکتای مقاوم در برابر تصادم، نسخه ۲) جانشین رسمی CUID نسخه ۱ است. این ابزار شناسههای کوتاه، رمزنگاریشده و مبهمی تولید میکند که برای استفاده به عنوان کلید اصلی در پایگاههای داده، URLها و سیستمهای توزیعشده مناسب هستند.
بر خلاف نسخه قبلی، CUID2 هیچ اطلاعاتی درباره زمان ایجاد، دستگاه میزبان یا فرآیندی که آن را تولید کرده فاش نمیکند. هر شناسه یک رشته تصادفی به نظر میرسد که با یک حرف کوچک تصادفی شروع میشود و با یک هش base-36 مشتقشده از SHA-512 ادامه مییابد. طول پیشفرض ۲۴ کاراکتر است، اما میتوانید آن را از ۲ تا ۳۲ کاراکتر تنظیم کنید.
CUID2 توسط ابزارهای مدرن پایگاه داده بهطور گسترده توصیه میشود. Prisma آن را به عنوان استراتژی پیشفرض شناسه برای @default(cuid()) خود پذیرفت، و PlanetScale، Neon و سایر ارائهدهندگان پایگاه داده بدون سرور CUID2 را صراحتاً به عنوان فرمت شناسه ترجیحی فهرست میکنند.
چرا CUID2 جایگزین CUID نسخه ۱ شد
CUID نسخه ۱، که در سال ۲۰۱۲ توسط اریک الیوت منتشر شد، یک پیشرفت بزرگ نسبت به UUIDهای ساده برای تولید شناسه در سمت کلاینت بود. با این حال، محققان امنیتی دو مشکل اساسی در طراحی آن کشف کردند:
- اثرانگشتگذاری: اثر انگشت میزبان جاسازیشده در هر مقدار CUID نسخه ۱ میتوانست برای شناسایی دستگاه یا فرآیندی که شناسه را تولید کرده استفاده شود و متادیتای عملیاتی را برای هر کسی که میتوانست شناسهها را مشاهده کند فاش کند.
- قابلیت پیشبینی: از آنجایی که CUID نسخه ۱ یک شمارنده یکنوا و یک بخش زماننگار را در خود داشت، مهاجمی که چندین شناسه را مشاهده کرده بود میتوانست محدوده تقریبی شناسههای آینده را پیشبینی کند و حملات شمارش را علیه APIهایی که از شناسهها به عنوان تنها بررسی مجوز استفاده میکنند فعال کند.
- هش غیر رمزنگاری: CUID نسخه ۱ از یک مرحله هشگذاری غیر رمزنگاری ساده استفاده میکرد که استانداردهای امنیتی مدرن را برآورده نمیکرد.
اریک الیوت، نویسنده اصلی، CUID نسخه ۱ را رسماً منسوخ اعلام کرد و CUID2 را از ابتدا برای رفع همه این مشکلات نوشت. الگوریتم جدید از Web Crypto API (SHA-512) استفاده میکند. همه اجزای قطعی حذف شدهاند و هر شناسه از نظر آماری مستقل از هر شناسه دیگری است.
اصول طراحی CUID2
CUID2 در مقابل CUID نسخه ۱ — مقایسه
جدول زیر تفاوتهای کلیدی بین CUID2 و CUID نسخه ۱ منسوخشده را خلاصه میکند. اگر در حال حاضر از CUID نسخه ۱ استفاده میکنید، مهاجرت به CUID2 توصیه میشود.
| ویژگی | CUID2 | CUID نسخه ۱ |
|---|---|---|
| امنیت | رمزنگاری (SHA-512) | غیر رمزنگاری (مبتنی بر اثر انگشت) |
| قابلیت پیشبینی | مبهم — بدون متادیتای فاششده | زماننگار + اثر انگشت در شناسه قابل مشاهده |
| طول | قابل تنظیم (۲-۳۲ کاراکتر) | ثابت ۲۵ کاراکتر |
| پیشوند | حرف تصادفی a-z | همیشه با «c» شروع میشود |
| توزیع | یکنواخت / هموار | بخشهای یکنوا افزایشی |
| وضعیت | بهطور فعال نگهداری میشود | توسط نویسنده اصلی منسوخ شده |
CUID2 در مقابل UUID نسخه ۴ — مقایسه
UUID نسخه ۴ استاندارد غالب برای شناسههای یکتای تصادفی است. CUID2 چندین مزیت عملی نسبت به UUID نسخه ۴ بدون بهخطر انداختن امنیت ارائه میدهد.
| ویژگی | CUID2 | UUID نسخه ۴ |
|---|---|---|
| طول پیشفرض | ۲۴ کاراکتر | ۳۶ کاراکتر (با خط تیره) |
| ایمن برای URL | بله — حروف کوچک a-z + ۰-۹ | نیاز به رمزگذاری دارد (شامل خط تیره) |
| طول سفارشی | بله (۲-۳۲) | خیر — همیشه ۱۲۸ بیت / ۳۶ کاراکتر |
| قابل مرتبسازی | خیر (طبق طراحی) | خیر (نسخه ۴ تصادفی است) |
| منبع آنتروپی | SHA-512 + Web Crypto | CSPRNG |
| مجموعه کاراکتر | Base-36 (a-z، ۰-۹) | هگزادسیمال + خط تیره |
مهمترین تفاوت، سطح آشنایی است: UUID نسخه ۴ یک استاندارد IETF (RFC 4122) است که توسط تقریباً هر پایگاه داده، زبان برنامهنویسی و چارچوب API بهطور آماده شناخته میشود. CUID2 یک استاندارد جامعه است با پشتیبانی رو به رشد اما نه همگانی. UUID نسخه ۴ را وقتی قابلیت همکاری با سیستمهای خارجی اولویت دارد انتخاب کنید؛ CUID2 را وقتی هر دو طرف را در اختیار دارید و شناسههای کوتاهتر و ایمن برای URL را ترجیح میدهید انتخاب کنید.
چه کسانی از CUID2 استفاده میکنند
CUID2 در سراسر اکوسیستم مدرن جاوااسکریپت و تایپاسکریپت پذیرش سریعی داشته است:
- Prisma — محبوبترین ORM تایپاسکریپت از CUID2 به عنوان پیشفرض توصیهشده برای فیلدهای
@idبا@default(cuid())در Prisma Schema نسخه ۲ به بالا استفاده میکند. - PlanetScale — مستندات و قالبهای starter آنها CUID2 را برای کلیدهای اصلی تولیدشده توسط اپلیکیشن برای جلوگیری از مشکلات عملکردی اسکن ترتیبی روی پلتفرم MySQL توزیعشدهشان توصیه میکنند.
- Drizzle ORM — یک helper پیشفرض
cuid2()داخلی برای تعریف ستونها ارائه میدهد. - boilerplateهای tRPC — بسیاری از قالبهای starter جامعه tRPC + Prisma با CUID2 به عنوان استراتژی کلید اصلی ارائه میشوند.
- T3 Stack — ابزار scaffolding create-t3-app از Prisma با پیشفرضهای CUID2 در فایلهای schema تولیدشده استفاده میکند.
مثالهای کد
بسته npm رسمی @paralleldrive/cuid2 یک 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"استفاده از CUID2 با schema Prisma:
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}تولید CUID2 در Node.js بدون بسته npm (فقط با Web Crypto API، همانطور که این ابزار در مرورگر انجام میدهد):
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"