ToolDeck

تولیدکننده NanoID

تولید شناسه‌های یکتای کوتاه امن برای URL با الفبای قابل تنظیم

الفبا

اندازه

تعداد

برای ساخت NanoID روی تولید کلیک کنید

NanoID چیست؟

NanoID یک تولیدکننده شناسه تصادفی کوچک، سریع و امن برای URL است. به‌طور پیش‌فرض رشته‌های ۲۱ کاراکتری با الفبای ۶۴ کاراکتری (A-Za-z0-9_-) تولید می‌کند و آنتروپی تقریبی ۱۲۶ بیتی فراهم می‌کند — قابل مقایسه با ۱۲۲ بیت UUID v4 اما در رشته‌ای کوتاه‌تر.

NanoID هیچ زمان‌نما یا داده ساختارمندی را جاسازی نمی‌کند. هر شناسه کاملاً تصادفی است و از مولد اعداد تصادفی امن رمزنگاری‌شده سیستم‌عامل تولید می‌شود (crypto.getRandomValues() در مرورگرها، crypto.randomBytes() در Node.js).

NanoID در برابر UUID v4

NanoID و UUID v4 هر دو تولیدکننده شناسه تصادفی هستند که از CSPRNG پشتیبانی می‌شوند. تفاوت‌های آن‌ها در قالب، طول و پشتیبانی اکوسیستم است:

ویژگیNanoID (پیش‌فرض)UUID v4
قالبالفبای عددی امن برای URL + _-هگزادسیمال با خط تیره
طول۲۱ کاراکتر (پیش‌فرض)۳۶ کاراکتر
آنتروپی~۱۲۶ بیت۱۲۲ بیت
امن برای URLبله — نیازی به رمزگذاری نیستبله (با خط تیره)
الفبا۶۴ کاراکتر (A-Za-z0-9_-)۱۶ کاراکتر (0-9a-f)
وابستگی‌هانیاز به بسته npm داردبومی (crypto.randomUUID)
قابل تنظیمبله — طول و الفباخیر
استانداردهیچ (کتابخانه جامعه‌محور)RFC 4122 / RFC 9562

UUID v4 را انتخاب کنید وقتی سازگاری با سیستم‌های خارجی اهمیت دارد — پایگاه‌های داده با ستون‌های UUID بومی، APIهایی که قالب UUID انتظار دارند، یا زیرساخت ثبت رویداد که UUIDها را تجزیه می‌کند. NanoID را انتخاب کنید وقتی شناسه‌های کوتاه‌تر می‌خواهید و کنترل کامل پشته را دارید.

احتمال تصادم بر اساس اندازه

احتمال تصادم NanoID به طول شناسه و نرخ تولید بستگی دارد. جدول زیر از الفبای پیش‌فرض ۶۴ کاراکتری استفاده می‌کند:

اندازه (کاراکتر)شناسه‌های ممکنایمنی در برابر تصادم
664~۱ در ۴.۵ میلیارد — ایمن برای چند هزار شناسه
864~۱ در ۴.۵ تریلیون — ایمن برای میلیون‌ها شناسه
1164~۱ در ۲.۸ کوادریلیون — ایمن برای میلیاردها شناسه
1664~۱ در ۱.۲ × 10^19 — ایمن برای تریلیون‌ها شناسه
2164~۱ در 10^30 — ایمن برای ۱۰۰ میلیارد شناسه در روز برای قرن‌ها
3264قابل مقایسه با UUID v4 (۱۲۲ بیت)
3636از UUID v4 فراتر می‌رود

اندازه پیش‌فرض ۲۱ کاراکتر برای تطابق با مقاومت تصادم UUID v4 (~۱۲۶ بیت) و در عین حال ۴۱٪ کوتاه‌تر بودن انتخاب شده است. برای اکثر برنامه‌ها، ۲۱ کاراکتر انتخاب مناسبی است.

الفباهای سفارشی

الفبای NanoID کاملاً قابل تنظیم است. این کتابخانه هر رشته‌ای از کاراکترهای یکتا را به عنوان الفبا می‌پذیرد و شناسه‌ها را فقط با استفاده از آن کاراکترها تولید می‌کند:

فقط اعدادA-Za-z0-9_-
از '0123456789' برای شناسه‌هایی که کاملاً عددی هستند استفاده کنید — برای کدهای SMS یا شناسه‌های به سبک PIN مفید است.
هگز با حروف کوچکA-Za-z0-9
از '0123456789abcdef' برای رشته‌های هگز فشرده بدون قالب خط تیره UUID استفاده کنید.
خوانا برای انسان0-9a-f
کاراکترهای بصری مبهم (0، O، 1، I، l) را حذف کنید تا شناسه‌هایی بسازید که کاربران ممکن است نیاز به تایپ دستی داشته باشند.
حوزه سفارشی0-9
از هر مجموعه کاراکتری مناسب برای برنامه خود استفاده کنید — مثلاً فقط مصوت‌ها و صامت‌ها برای شناسه‌های قابل تلفظ.

مهم: از nanoid/non-secure فقط برای برنامه‌هایی استفاده کنید که نیاز به امنیت ندارند (مثلاً شناسه‌های عناصر رابط کاربری). برای هر شناسه‌ای که باید غیرقابل حدس باشد، همیشه از default import امن استفاده کنید.

نحوه تولید تصادفی بودن در NanoID

NanoID از مولد اعداد شبه‌تصادفی امن رمزنگاری‌شده (CSPRNG) سیستم‌عامل استفاده می‌کند. در مرورگرها این crypto.getRandomValues() است؛ در Node.js این crypto.randomFillSync() است. این همان منبع آنتروپی است که برای کلیدهای نشست TLS استفاده می‌شود — بسیار قوی‌تر از Math.random().

نمونه‌برداری رد (جلوگیری از انحراف پیمانه‌ای)

یک رویکرد ساده برای تولید کاراکترهای تصادفی این است: یک بایت تصادفی (0 تا 255) بگیرید و byte % alphabetSize را محاسبه کنید. این انحراف پیمانه‌ای ایجاد می‌کند — برخی کاراکترها کمی بیشتر از دیگران ظاهر می‌شوند وقتی اندازه الفبا مضربی از 256 نباشد.

NanoID این انحراف را با نمونه‌برداری رد از بین می‌برد:

  1. کوچک‌ترین ماسک توان-دو که اندازه الفبا را پوشش می‌دهد تعیین کنید (مثلاً برای الفبای ۶۴ کاراکتری، ماسک ۶۳ = 0b00111111 است)
  2. بایت‌های تصادفی تولید کنید و ماسک را اعمال کنید: byte & mask
  3. اگر مقدار ماسک‌شده در محدوده الفبا بود، از آن استفاده کنید. در غیر این صورت، آن را دور بیندازید و دوباره تلاش کنید.

این یعنی برخی بایت‌های تصادفی دور انداخته می‌شوند، اما نتیجه توزیع کاملاً یکنواخت بر روی الفبا است — هیچ کاراکتری بیشتر از دیگری محتمل نیست.

How the algorithm works — step by step
// Pure browser — no npm package needed
function generateNanoid(alphabet, size) {
  const mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
  const step = Math.ceil((1.6 * mask * size) / alphabet.length)
  let id = ''
  while (id.length < size) {
    const bytes = crypto.getRandomValues(new Uint8Array(step))
    for (const byte of bytes) {
      const idx = byte & mask
      if (idx < alphabet.length) {
        id += alphabet[idx]
        if (id.length === size) break
      }
    }
  }
  return id
}

const URL_SAFE = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
generateNanoid(URL_SAFE, 21)  // → "V1StGXR8_Z5jdHi6B-myT"

پشتیبانی محیط

Browser
مرورگرهای مدرن (Chrome 37+، Firefox 34+، Safari 7+) — از crypto.getRandomValues() استفاده می‌کند
Node.js 14+
Node.js 14.18+ — از crypto.randomFillSync() استفاده می‌کند
Deno
Deno — از crypto.getRandomValues() استفاده می‌کند
Bun
React Native — از expo-crypto یا polyfill react-native-get-random-values استفاده می‌کند
Edge / Cloudflare Workers
محیط‌های Edge (Cloudflare Workers، Vercel Edge) — Web Crypto API در دسترس است
React Native
Bun — پشتیبانی بومی از crypto

نمونه کدها

JavaScript / TypeScript

JavaScript
// npm i nanoid
import { nanoid } from 'nanoid'
nanoid()          // → "V1StGXR8_Z5jdHi6B-myT" (21 chars, URL-safe)
nanoid(8)         // → "Uakgb_J5" (custom size)

// Custom alphabet
import { customAlphabet } from 'nanoid'
const hexId  = customAlphabet('0123456789abcdef', 16)
hexId()       // → "4f3a1b8c9d2e0f7a"

const numId  = customAlphabet('0123456789', 8)
numId()       // → "30812894"

مرورگر (CDN)

NanoID را می‌توان مستقیماً در مرورگر از طریق import از CDN استفاده کرد. برای نمونه‌سازی سریع نیازی به مرحله ساخت نیست.

JavaScript
// Pure browser — no npm package needed
function generateNanoid(alphabet, size) {
  const mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
  const step = Math.ceil((1.6 * mask * size) / alphabet.length)
  let id = ''
  while (id.length < size) {
    const bytes = crypto.getRandomValues(new Uint8Array(step))
    for (const byte of bytes) {
      const idx = byte & mask
      if (idx < alphabet.length) {
        id += alphabet[idx]
        if (id.length === size) break
      }
    }
  }
  return id
}

const URL_SAFE = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
generateNanoid(URL_SAFE, 21)  // → "V1StGXR8_Z5jdHi6B-myT"

Python

Python
# pip install nanoid
from nanoid import generate

generate()              # → "V1StGXR8_Z5jdHi6B-myT"
generate(size=8)        # → "Uakgb_J5"
generate('0123456789abcdef', 16)  # custom alphabet + size

Node.js (CommonJS)

JavaScript
// Node.js — stdlib only, no npm needed
const { randomFillSync } = require('crypto')

function nanoid(alphabet, size) {
  const mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
  const step = Math.ceil((1.6 * mask * size) / alphabet.length)
  let id = ''
  while (id.length < size) {
    const bytes = randomFillSync(Buffer.alloc(step))
    for (const byte of bytes) {
      const idx = byte & mask
      if (idx < alphabet.length) { id += alphabet[idx]; if (id.length === size) break }
    }
  }
  return id
}

سوالات متداول

آیا NanoID از نظر رمزنگاری امن است؟
بله — هنگام استفاده از وارد کردن پیش‌فرض، NanoID شناسه‌ها را با استفاده از CSPRNG سطح سیستم‌عامل تولید می‌کند (crypto.getRandomValues در مرورگرها، crypto.randomFillSync در Node.js). این همان منبع آنتروپی است که برای تولید کلید رمزنگاری استفاده می‌شود. مقادیر NanoID برای توکن‌های نشست، کلیدهای API و سایر شناسه‌های حساس از نظر امنیتی مناسب هستند.
آیا می‌توانم از NanoID به عنوان کلید اصلی پایگاه داده استفاده کنم؟
بله. رشته‌های NanoID امن برای URL هستند و می‌توانند به عنوان ستون‌های CHAR یا VARCHAR ذخیره شوند. با این حال، NanoID هیچ مؤلفه زمان‌نمایی ندارد، بنابراین شناسه‌ها بر اساس ترتیب تولید قابل مرتب‌سازی نیستند — این باعث تکه‌تکه شدن ایندکس B-tree در نرخ‌های درج بالا می‌شود، مشابه UUID v4. برای کلیدهای اصلی مرتب‌شده بر اساس زمان، به جای آن از ULID یا UUID v7 استفاده کنید.
NanoID چگونه با crypto.randomUUID() مقایسه می‌شود؟
هر دو از CSPRNG استفاده می‌کنند و تصادفی بودن قوی فراهم می‌آورند. crypto.randomUUID() بومی است (بدون وابستگی)، رشته‌های UUID v4 هگزادسیمال با خط تیره ۳۶ کاراکتری تولید می‌کند، و توسط پایگاه‌های داده و APIها به‌طور جهانی شناخته می‌شود. NanoID نیاز به یک بسته npm دارد اما رشته‌های کوتاه‌تری (پیش‌فرض ۲۱ کاراکتر) با الفبای قابل تنظیم تولید می‌کند. برای اکثر موارد، ترجیح دهید از crypto.randomUUID() استفاده کنید تا نیازی به dependency خارجی نداشته باشید.
اگر از NanoID بسیار کوتاه استفاده کنم چه می‌شود؟
شناسه‌های کوتاه (مثلاً ۶ تا ۸ کاراکتر) احتمال تصادم به‌طور قابل توجهی بالاتری دارند. یک NanoID ۶ کاراکتری از الفبای پیش‌فرض ۶۴ کاراکتری تنها ~۶۸ میلیارد مقدار ممکن دارد — قبل از اینکه خطر تصادم غیرقابل چشم‌پوشی شود مناسب چند هزار شناسه است. از جدول احتمال تصادم بالا استفاده کنید تا اندازه مناسب برای حجم مورد انتظار شناسه‌های خود را انتخاب کنید.
آیا می‌توانم از NanoID در مرورگر بدون npm استفاده کنم؟
بله. NanoID از import ESM از CDN (مثلاً jsDelivr یا esm.sh) پشتیبانی می‌کند. آن را به عنوان یک ماژول در یک تگ script با type="module" import کنید. این برای نمونه‌سازی سریع مفید است اما برای محیط تولید توصیه نمی‌شود — به یک نسخه خاص پین کنید و در نظر بگیرید که اسکریپت را خودتان میزبانی کنید.
آیا NanoID در همه محیط‌ها کار می‌کند؟
NanoID در همه مرورگرهای مدرن، Node.js، Deno، Bun، Cloudflare Workers و Vercel Edge Functions کار می‌کند. برای React Native، یک polyfill برای getRandomValues لازم است (react-native-get-random-values). این کتابخانه به گونه‌ای طراحی شده که مستقل از محیط باشد و API crypto موجود را به‌طور خودکار شناسایی می‌کند.