ویژگی تصویر

کتابخانه secrets در پایتون — تولید اعداد و توکن‌های امن برای کاربردهای واقعی

  /  پایتون   /  کتابخانه secrets در پایتون
بنر تبلیغاتی الف

در برنامه‌نویسی امنیت‌محور، تولید داده‌های تصادفیِ ضدرابطه (cryptographically secure) حیاتی است. ماژول secrets در پایتون برای این منظور طراحی شده است و جایگزین امنی برای ماژول random به شمار می‌آید. در این مقاله به توضیح مفاهیم، توابع کلیدی، مثال‌های عملی و نکات حرفه‌ای در استفاده از secrets می‌پردازیم.

چرا از secrets به جای random استفاده کنیم؟

ماژول random برای شبیه‌سازی و بازی‌ها مناسب است و از الگوریتم‌هایی استفاده می‌کند که قابل پیش‌بینی هستند. اما تولید توکن‌های نشست (session)، رمز عبور موقت، یا کلیدهای API باید غیرقابل پیش‌بینی و مقاوم در برابر حملات باشند؛ این‌جا است که secrets بر پایه منابع تصادفی سطح سیستم (مانند /dev/urandom در لینوکس یا CryptoAPI در ویندوز) عمل می‌کند.

توابع کلیدی و تفاوت‌ها

تابعشرح
token_bytes(nbytes=None)تعداد بایت تصادفی برمی‌گرداند؛ خوب برای تولید کلید خام
token_hex(nbytes=None)نشان‌دهندهٔ هگزادسیمال از token_bytes
token_urlsafe(nbytes=None)تویکن امن قابل استفاده در URL (Base64-safe)
randbelow(exclusive_upper)عدد صحیح تصادفی در محدودهٔ [0, exclusive_upper)
choice(sequence)انتخاب تصادفی یک عنصر از توالی
compare_digest(a, b)مقایسهٔ مقاوم در برابر حملات زمانی (timing attacks)

مثال‌های عملی

تولید یک توکن امن برای نشست کاربر یا تایید ایمیل:

import secrets

# تولید توکن قابل قرارگیری در URL
token = secrets.token_urlsafe(32)
print(token)

در این مثال، تابع token_urlsafe(32) حدود 32 بایت تصادفی تولید می‌کند و آن را به یک رشتهٔ Base64 ایمن برای URL تبدیل می‌کند. این رشته برای نشانه‌گذاری نشست یا لینک‌های تایید ایمیل مناسب است.

تولید عدد تصادفی امن در بازه مشخص (مثلاً برای OTP یا کد یک‌بار مصرف):

import secrets

# تولید عدد بین 0 تا 999999 برای OTP شش‌رقمی
otp = secrets.randbelow(10**6)
otp_str = f"{otp:06d}"
print(otp_str)

در بالا از randbelow استفاده شده تا عددی در محدودهٔ 0 تا 999999 تولید شود و سپس با فرمت صفرپر شده شش رقمی نمایش داده شده است. این روش امن‌تر از تولید با random.randint است.

تولید رمز عبور قوی به‌صورت تصادفی:

import secrets
import string

alphabet = string.ascii_letters + string.digits + string.punctuation
password = ''.join(secrets.choice(alphabet) for _ in range(16))
print(password)

در این کد، هر کاراکتر با استفاده از secrets.choice انتخاب می‌شود که نسبت به random.choice امنیت بالاتری دارد. توجه داشته باشید که طول و انواع کاراکترها را با توجه به سیاست امنیتی تعیین کنید.

مقایسهٔ امن رشته‌ها برای احراز اصالت

هنگام مقایسهٔ توکن‌ها یا امضاها، استفادهٔ معمولی از == ممکن است در برابر حملات زمانی آسیب‌پذیر باشد. از secrets.compare_digest استفاده کنید:

import secrets

def verify_token(provided, expected):
    return secrets.compare_digest(provided, expected)

این تابع مقایسه‌ای زمان‌ثابت انجام می‌دهد و از افشای اطلاعات از طریق اندازه‌گیری زمان جلوگیری می‌کند.

نکات حرفه‌ای و بهینه‌سازی‌ها

  • برای تولید کلیدهای رمزنگاریِ بلندمدت از کتابخانه‌های اختصاصی مثل cryptography استفاده کنید؛ secrets برای توکن‌ها و مقادیر تصادفی کافی و مناسب است ولی مدیریت کلیدهای پیچیده نیاز به طراحی گسترده‌تر دارد.
  • هیچ‌گاه برای تولید توکن‌ها یا رمزعبورها از random یا توابع مبتنی بر زمان استفاده نکنید — آنها قابل پیش‌بینی‌اند.
  • برای ایجاد رشته‌های قابل انتقال در URL یا کوکی‌ها، از token_urlsafe استفاده کنید تا کاراکترهای نامناسب حذف شوند.
  • نمک (salt) برای هش‌کردن رمز عبور لازم است اما نیازی نیست که مخفی بماند. نمک‌ها باید یکتا و تصادفی باشند، اما نگه‌داری کلید‌ها و توکن‌ها باید محرمانه انجام شود.
  • در سیستم‌های توزیع‌شده، برای تولید عدد تصادفی امن به‌جای اعتماد به وضعیت محلی تصادفی، از منابع مرکزی یا کتابخانه‌های طراحی‌شده برای آن استفاده کنید تا از همگام‌سازی نادرست جلوگیری شود.

موارد استفاده رایج

  • توکن جلسات (session tokens) برای وب‌اپلیکیشن‌ها
  • توکن‌های تایید ایمیل و بازنشانی رمز عبور
  • کدهای OTP و MFA (تأیید دومرحله‌ای)
  • ایجاد کلیدهای موقت برای API
  • تولید نمک‌های یکتا برای هش‌کردن رمزعبورها

ملاحظات امنیتی و اندازهٔ توکن

طول توکن را بر اساس تهدیدات تعیین کنید. برای مثال، اگر یک توکن 32 بایت تصادفی تولید کنید، دارای 256 بیت آنتروپی است که برای بیشتر کاربردها کافی است. اما برای توکن‌های بلندمدت یا کلیدها، طراحی امنیتی باید بر اساس تهدیدات خاص و استانداردها (مثلاً NIST) انجام شود.

نمونهٔ بهبود و توضیحات اضافی

ممکن است بخواهید هنگام تولید توکن، آن را همراه با اطلاعات کاربر یا زمان‌سنجی HMAC کنید تا بتوانید به‌صورت امن‌تر اعتبارسنجی کنید. نمونه زیر HMAC ساده را نشان می‌دهد:

import secrets
import hmac
import hashlib

# secret_key should be stored securely (e.g., environment variable or vault)
secret_key = secrets.token_bytes(32)

def make_token(user_id):
    nonce = secrets.token_urlsafe(16)
    msg = f"{user_id}:{nonce}".encode()
    signature = hmac.new(secret_key, msg, hashlib.sha256).hexdigest()
    return f"{user_id}:{nonce}:{signature}"

def verify_token(token):
    try:
        user_id, nonce, signature = token.split(':')
    except ValueError:
        return False
    msg = f"{user_id}:{nonce}".encode()
    expected = hmac.new(secret_key, msg, hashlib.sha256).hexdigest()
    return secrets.compare_digest(signature, expected)

در این الگو، توکن شامل یک nonce تصادفی و امضای HMAC است. کلید HMAC باید به‌صورت امن نگهداری شود. برای مقیاس بالا، مدیریت کلید از طریق سرویس مدیریت کلید (KMS) توصیه می‌شود.

خلاصه

ماژول secrets ابزار اصلی پایتون برای تولید داده‌های تصادفی امن است و جایگزینی ضروری برای random در کاربردهای امنیتی می‌باشد. با درک توابع کلیدی، رعایت نکات امنیتی و طراحی مناسب توکن‌ها می‌توانید از آسیب‌پذیری‌های رایج جلوگیری کنید و ساختار امنی برای مدیریت احراز هویت و کلیدها پیاده‌سازی کنید.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: