PYOTP(1) PyOTP PYOTP(1)

pyotp - کتابخانه پایتون برای تولید و اعتبارسنجی گذرواژه‌های یک‌بارمصرف

PyOTP یک کتابخانه پایتون برای تولید و اعتبارسنجی گذرواژه‌های یک‌بارمصرف (OTP) است. این کتابخانه می‌تواند برای پیاده‌سازی روش‌های احراز هویت دوعاملی (2FA) یا چندعاملی (MFA) در برنامه‌های وب و سایر سامانه‌هایی که نیازمند ورود کاربر هستند استفاده شود.

استانداردهای باز MFA در RFC 4226 https://tools.ietf.org/html/rfc4226 (الگوریتم رمز یک‌بارمصرف مبتنی بر هش - HOTP) و RFC 6238 https://tools.ietf.org/html/rfc6238 (الگوریتم رمز یک‌بارمصرف مبتنی بر زمان - TOTP) تعریف شده‌اند. ابزار PyOTP پشتیبانی سمت سرور را برای هر دوی این استانداردها پیاده‌سازی می‌کند. پشتیبانی سمت کاربر را می‌توان با ارسال کدهای احراز هویت از طریق پیامک یا ایمیل (HOTP) یا برای TOTP با راهنمایی کاربران جهت استفاده از Google Authenticator https://en.wikipedia.org/wiki/Google_Authenticator، Authy https://www.authy.com یا سایر برنامه‌های سازگار فراهم کرد. کاربران می‌توانند با استفاده از دوربین تلفن همراه خود و اسکن کدهای تصویری QR با قالب otpauth:// https://github.com/google/google-authenticator/wiki/Key-Uri-Format که توسط PyOTP فراهم می‌شود، به آسانی توکن‌های احراز هویت را در برنامه‌های خود پیکربندی کنند.

توسعه‌دهندگان و پیاده‌سازان باید بخش‌های الزامات امنیتی HOTP https://tools.ietf.org/html/rfc4226#section-7 و ملاحظات امنیتی TOTP https://tools.ietf.org/html/rfc6238#section-5 از RFCهای مربوطه را مطالعه و رعایت کنند. در کمترین حالت، پیاده‌سازان برنامه باید این چک‌لیست را دنبال نمایند:

  • محرمانگی مسیر انتقال را با استفاده از HTTPS تضمین کنید
  • محرمانگی کلیدهای محرمانه HOTP/TOTP را با ذخیره آن‌ها در یک پایگاه داده با دسترسی کنترل‌شده تضمین کنید
  • با رد کردن رمزهای یک‌بارمصرف استفاده‌شده توسط کاربر، از حملات بازپخش (Replay Attacks) جلوگیری کنید (این امر مستلزم ذخیره آخرین برچسب زمانی احراز هویت، OTP یا هش آن در پایگاه داده شما و رد کردن OTP در صورت تطابق است)
  • حملات بروت‌فورس علیه سازوکار ورود به برنامه را مهار (محدودسازی نرخ) کنید (به RFC 4226، بخش 7.3 مراجعه کنید)
  • هنگام پیاده‌سازی برنامه‌های جدید، پشتیبانی از FIDO U2F https://en.wikipedia.org/wiki/Universal_2nd_Factor یا WebAuthn https://www.w3.org/TR/webauthn را علاوه بر یا به جای HOTP/TOTP در نظر بگیرید. شیوه U2F از رمزنگاری نامتقارن برای پرهیز از طراحی مبتنی بر کلید مشترک استفاده می‌کند که راهکار MFA شما را در برابر حملات سمت سرور مقاوم‌تر می‌سازد. همچنین U2F سخت‌افزاری، کلید محرمانه کاربر را در یک دستگاه تک‌منظوره اختصاصی ایزوله می‌کند که کاربران شما را در برابر حملات سمت کاربر ایمن می‌سازد. علاوه بر این، U2F با مقیدسازی خودکار اطلاعات هویتی به شناسه‌های Relying Party (نام‌های مبدا یا دامنه برنامه)، محافظت در برابر حملات فیشینگ را افزایش می‌دهد. یک پیاده‌سازی از FIDO U2F/WebAuthn، پروژه هم‌خانواده PyOTP به نام PyWARP https://github.com/pyauth/pywarp است.

همچنین توصیه می‌کنیم پیاده‌سازان مستندات زیر را برای مروری جامع بر بهترین روش‌های احراز هویت مطالعه کنند: OWASP Authentication Cheat Sheet https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md و NIST SP 800-63-3: Digital Authentication Guideline https://pages.nist.gov/800-63-3

  • رمزهای یک‌بارمصرف بر پایه یک کلید محرمانه مشترک کار می‌کنند که هم روی گوشی و هم روی سرور ذخیره می‌شود
  • رمزهای یک‌بارمصرف را می‌توان روی گوشی بدون نیاز به اتصال اینترنت تولید کرد
  • رمزهای یک‌بارمصرف همواره باید به عنوان عامل دوم احراز هویت به کار روند (اگر گوشی شما مفقود شود، حساب کاربری شما همچنان با گذرواژه ایمن است)
  • برنامه Google Authenticator و سایر برنامه‌های کلاینت OTP امکان ذخیره‌سازی چندین کلید محرمانه OTP و بارگذاری آن‌ها را با استفاده از QR Code فراهم می‌کنند

pip install pyotp

import pyotp
import time
totp = pyotp.TOTP('base32secret3232')
totp.now() # => '492039'
# OTP verified for current time
totp.verify('492039') # => True
time.sleep(30)
totp.verify('492039') # => False

import pyotp
hotp = pyotp.HOTP('base32secret3232')
hotp.at(0) # => '260182'
hotp.at(1) # => '055283'
hotp.at(1401) # => '316439'
# OTP verified with a counter
hotp.verify('316439', 1401) # => True
hotp.verify('316439', 1402) # => False

یک تابع کمکی برای تولید کلید محرمانه ۳۲ کاراکتری در قالب base32 و سازگار با Google Authenticator و سایر برنامه‌های OTP فراهم شده است:

pyotp.random_base32()

برخی برنامه‌ها ترجیح می‌دهند کلید محرمانه به صورت رشته‌ای با کدگذاری هگزادسیمال قالب‌بندی شود:

pyotp.random_hex()  # returns a 40-character hex-encoded secret

کتابخانه PyOTP با برنامه Google Authenticator در iPhone و Android و همچنین سایر برنامه‌های OTP مانند Authy کار می‌کند. همچنین PyOTP شامل قابلیت تولید URIهای پیکربندی جهت استفاده با اسکنر QR Code داخلی این برنامه‌های کلاینت MFA است:

pyotp.totp.TOTP('JBSWY3DPEHPK3PXP').provisioning_uri(name='alice@google.com', issuer_name='Secure App')
>>> 'otpauth://totp/Secure%20App:alice%40google.com?secret=JBSWY3DPEHPK3PXP&issuer=Secure%20App'
pyotp.hotp.HOTP('JBSWY3DPEHPK3PXP').provisioning_uri(name="alice@google.com", issuer_name="Secure App", initial_count=0)
>>> 'otpauth://hotp/Secure%20App:alice%40google.com?secret=JBSWY3DPEHPK3PXP&issuer=Secure%20App&counter=0'

سپس این آدرس اینترنتی می‌تواند به صورت یک QR Code رندر شود (برای نمونه با https://github.com/soldair/node-qrcode) تا کاربر آن را اسکن کرده و به فهرست اعتبارسنج‌های OTP خود بیفزاید.

تجزیه این نشانی‌ها نیز پشتیبانی می‌شود:

pyotp.parse_uri('otpauth://totp/Secure%20App:alice%40google.com?secret=JBSWY3DPEHPK3PXP&issuer=Secure%20App')
>>> <pyotp.totp.TOTP object at 0xFFFFFFFF>
pyotp.parse_uri('otpauth://hotp/Secure%20App:alice%40google.com?secret=JBSWY3DPEHPK3PXP&issuer=Secure%20App&counter=0'
>>> <pyotp.totp.HOTP object at 0xFFFFFFFF>

بارکد زیر را با برنامه OTP تلفن همراه خود (مانند Google Authenticator) اسکن کنید: [image]

اکنون دستورات زیر را اجرا کرده و خروجی را مقایسه نمایید:

import pyotp
totp = pyotp.TOTP("JBSWY3DPEHPK3PXP")
print("Current OTP:", totp.now())

مشارکت‌های متفرقه زیر توسط استانداردی توصیف نشده‌اند، رسماً پشتیبانی نمی‌شوند و صرفاً جهت ارجاع ارائه شده‌اند:

•
pyotp.contrib.Steam(): یک پیاده‌سازی از TOTP برای پلتفرم Steam. از همان واسط برنامه‌نویسی pyotp.TOTP() استفاده می‌کند.

برای برنامه‌های جدید:

این بسته از استاندارد نسخه‌بندی معنایی Semantic Versioning 2.0.0 http://semver.org پیروی می‌کند. برای کنترل تغییرات، توصیه می‌شود توسعه‌دهندگان برنامه نسخه بسته را تثبیت (pin) کرده و آن را با استفاده از pip-tools https://github.com/jazzband/pip-tools یا ابزارهای مشابه مدیریت کنند. برای توسعه‌دهندگان کتابخانه، تثبیت نسخه اصلی پیشنهاد می‌شود. [image]
https://github.com/pyauth/pyotp/actions[image]
https://codecov.io/github/pyauth/pyotp?branch=master[image]
https://pypi.python.org/pypi/pyotp[image]
https://pypi.python.org/pypi/pyotp[image]
https://pyotp.readthedocs.io.INDENT 0.0

شناسه URI پیکربندی را برای OTP تجزیه می‌کند؛ هم برای TOTP و هم برای HOTP کار می‌کند.
پارامترها:
uri -- نشانی hotp/totp URI برای تجزیه
بازگشتی:
شیء OTP

مدیریت‌کننده شمارنده‌های OTP مبتنی بر زمان.
یک عدد صحیح به عنوان برچسب زمانی یونیکس یا یک شیء datetime را می‌پذیرد.

برای دریافت مدت زمان تا تغییر بعدی کد زمانی (ثانیه‌های باقی‌مانده تا انقضای OTP فعلی)، به جای آن از این روش استفاده کنید:

totp = pyotp.TOTP(...)
time_remaining = totp.interval - datetime.datetime.now().timestamp() % totp.interval
پارامترها:
  • for_time -- زمان مورد نظر برای تولید OTP
  • counter_offset -- میزان تیک‌های اضافه شونده به شمارنده زمان
بازگشتی:
مقدار OTP
تولید OTP برای زمان جاری
بازگشتی:
مقدار OTP
نشانی URI پیکربندی را برای OTP برمی‌گرداند. این مقدار می‌تواند در یک QR Code کدگذاری شده و برای پیکربندی برنامه‌های OTP مانند Google Authenticator به کار رود.
یک شیء datetime بدون منطقه زمانی (for_time.tzinfo is None) یا با منطقه زمانی را به عنوان آرگومان پذیرفته و مقدار شمارنده متناظر (timecode) را برمی‌گرداند.
رمز OTP ارسال‌شده را با OTP زمان فعلی اعتبارسنجی می‌کند.
پارامترها:
  • otp -- مقدار OTP مورد نظر جهت بررسی
  • for_time -- زمانی که OTP در آن بررسی می‌شود (پیش‌فرض زمان جاری است)
  • valid_window -- بازه اعتبار را به این تعداد تیک شمارنده قبل و بعد از مقدار فعلی گسترش می‌دهد
بازگشتی:
در صورت موفقیت‌آمیز بودن اعتبارسنجی True، در غیر این صورت False
مدیریت‌کننده شمارنده‌های OTP مبتنی بر HMAC.
مقدار OTP را برای شمارنده داده‌شده تولید می‌کند.
پارامترها:
count -- شمارنده HMAC برای OTP
بازگشتی:
مقدار OTP
نشانی URI پیکربندی را برای OTP برمی‌گرداند. این مقدار می‌تواند در یک QR Code کدگذاری شده و برای پیکربندی برنامه‌های OTP مانند Google Authenticator به کار رود.
پارامترها:
  • name -- نام حساب کاربری
  • initial_count -- مقدار اولیه شمارنده HMAC، پیش‌فرض 0 است
  • issuer_name -- نام صادرکننده OTP؛ این عنوان سازمان در ورودی Authenticator خواهد بود
بازگشتی:
نشانی provisioning URI
رمز OTP ارسال‌شده را در برابر OTP شمارنده فعلی اعتبارسنجی می‌کند.
پارامترها:
  • otp -- مقدار OTP مورد نظر جهت بررسی
  • counter -- شمارنده HMAC برای OTP
نشانی URI پیکربندی را برای OTP برمی‌گرداند؛ هم برای TOTP و هم برای HOTP کار می‌کند.

سپس می‌توان این مقدار را در یک QR Code کدگذاری کرده و برای پیکربندی برنامه Google Authenticator استفاده نمود.

جهت استفاده داخلی ماژول.

پارامترها:
  • secret -- کلید محرمانه hotp/totp استفاده‌شده برای تولید URI
  • name -- نام حساب کاربری
  • initial_count -- مقدار اولیه شمارنده، پیش‌فرض None است. در صورت None بودن، نوع OTP به عنوان TOTP در نظر گرفته می‌شود.
  • issuer -- نام صادرکننده OTP؛ این عنوان سازمان در ورودی Authenticator خواهد بود
  • algorithm -- الگوریتم استفاده‌شده در تولید OTP.
  • digits -- طول کد تولیدشده OTP.
  • period -- تعداد ثانیه‌هایی که تولیدکننده OTP برای انقضای هر کد تنظیم شده است.
  • kwargs -- سایر پارامترهای query string برای گنجاندن در URI
بازگشتی:
نشانی provisioning uri
مقایسه رشته مقاوم در برابر حملات تحلیل زمانی (Timing attacks).

مقایسه عادی با == در اولین نویسه نامطابق متوقف می‌شود (short-circuit). این تابع با پیمایش کل رشته از این مشکل جلوگیری می‌کند، هرچند همچنان طول برابر رشته‌ها در برابر حمله زمانی آشکار می‌شود.

  • رفع خطای تجزیه دونقطه کدگذاری‌شده در نام صادرکننده/حساب در parse_uri (#187)
  • ساده‌سازی و بهبود کارایی generate_otp() در کلاس Steam (#179)
  • بررسی تابع خلاصه‌ساز جهت جلوگیری از بروز خطا در تولید OTP (#170)
  • نادیده گرفتن پارامترهای غیراستاندارد otpauth
  • استفاده از رشته‌ها به عنوان آرگومان‌های پیش‌فرض تغییرناپذیر (#162)

  • افزودن پشتیبانی از Steam TOTP در parse_uri() (#153)
  • بهبود تست‌ها و مستندات

  • تغییر تولید OTP جهت اجرا در زمان ثابت (constant time) (#148)
  • بهبود مستندات
  • حذف پشتیبانی از پایتون 3.6؛ آغاز پشتیبانی از پایتون 3.11

  • پشتیبانی از Steam TOTP (#142)
  • به‌روزرسانی‌های ساخت، آزمون و مستندات

  • افزایش طول پیش‌فرض و کمینه کلید محرمانه base32 به ۳۲ و کلید هگز به ۴۰ (۱۶۰ بیت طبق توصیه RFC) (#115).
  • رفع اشکالی که در آن provisioning_uri پس از فراخوانی verify() نتایج نامعتبر برمی‌گرداند (#115).

•
تابع parse_uri پارامتر اختیاری تصویر را می‌پذیرد و نادیده می‌گیرد (#114)

  • افزودن پارامتر اختیاری تصویر به provisioning_uri (#113)
  • پشتیبانی از کدهای ۷ رقمی در ‘parse_uri’ (#111)
  • افزایش طول پیش‌فرض و کمینه کلید محرمانه base32 به ۲۶

  • تابع parse_uri: رفع مدیریت دوره تناوب و شمارنده (#108)
  • افزودن پشتیبانی از datetime با منطقه زمانی مشخص به عنوان آرگومان در TOTP.timecode() (#107)

  • اصلاح نوع داده برای at(for_time) (#85)
  • افزودن پشتیبانی از تجزیه نشانی‌های provisioning URI (#84)
  • ایجاد خطا هنگام تلاش برای تولید کلید محرمانه بسیار کوتاه (کلید باید دست‌کم ۱۲۸ بیت باشد)
  • افزودن تابع random_hex (#82)

•
اصلاح رفتار مقایسه در پایتون 2.7

  • اصلاح مقایسه نویسه‌های یونیکد (#78)
  • اصلاحات جزئی در مستندات و تست‌ها

  • استفاده random_base32() از ‘secrets’ به عنوان منبع اعداد تصادفی (#66)
  • مستندات: افزودن ملاحظات امنیتی، حداقل چک‌لیست امنیتی و سایر بهبودها
  • به‌روزرسانی setup.py جهت ارجاع به مجوز صحیح

•
اصلاح آزمون‌ها در رابطه با نقل‌قول دوتایی در نشانی‌های provisioning URI

  • نقل‌قول پارامتر صادرکننده در query string در provisioning_uri. رفع مشکل #47.
  • ایجاد استثنا در صورت ارسال عدد صحیح منفی به at() (#41).
  • بهبودهای مستندات و زیرساخت انتشار.

  • بازگردانی سازگاری با پایتون 2.6 (البته پایتون 2.6 پشتیبانی نمی‌شود)
  • بهبودهای مستندات و تست‌ها
  • اصلاح اسکریپت زیرساخت انتشار، بخش ۲

  • بازگردانی سازگاری با پایتون 2.6 (البته پایتون 2.6 پشتیبانی نمی‌شود)
  • بهبودهای مستندات و تست‌ها
  • اصلاح اسکریپت زیرساخت انتشار

  • بازگردانی سازگاری با پایتون 2.6 (البته پایتون 2.6 پشتیبانی نمی‌شود)
  • بهبودهای مستندات و تست‌ها

  • پرهیز از استفاده از python-future؛ وابستگی‌های فرعی دارد که سازگاری را محدود می‌کنند (#34)
  • موفقیت‌آمیز بودن مجموعه آزمون‌ها روی پلتفرم‌های ۳۲ بیتی (#30)
  • اصلاح مقاومت در برابر حمله تحلیل زمانی: عدم افشای طول رشته به مهاجم. با تشکر از Eeo Jun (#28).
  • پشتیبانی از پارامترهای algorithm، digits و period در provisioning_uri. با تشکر از Dionisio E Alonso (#33).
  • اصلاحات جزئی نگارش و زیرساخت بسته‌بندی.

•
نسخه 2.2.1 را ببینید

  • افزودن پشتیبانی از بازه گسترش‌یافته به TOTP.verify. با تشکر از Zeev Rotshtein (PR #19).
  • مدیریت پدینگ مفقود در کلید کدگذاری‌شده. با تشکر از Kun Yan (#20).
  • اصلاحات متفرقه.

•
رفع مشکل بسته‌بندی در نسخه 2.0.0 که مانع از نصب با easy_install می‌شد.

•
متدهای pyotp.HOTP.at()، pyotp.TOTP.at() و pyotp.TOTP.now() اکنون به جای اعداد صحیح، رشته برمی‌گردانند. با تشکر از Rohan Dhaimade (PR #16).

  • آغاز ثبت تغییرات در گزارش تغییرات.
  • به‌روزرسانی مستندات.
  • معرفی یکپارچه‌سازی با Travis CI.

•
انتشار اولیه.

مشارکت‌کنندگان PyOTP

مشارکت‌کنندگان PyOTP

June 16, 2026