216 lines
9.6 KiB
Plaintext
216 lines
9.6 KiB
Plaintext
Metadata-Version: 2.1
|
|
Name: pyotp
|
|
Version: 2.9.0
|
|
Summary: Python One Time Password Library
|
|
Home-page: https://github.com/pyotp/pyotp
|
|
Author: PyOTP contributors
|
|
Author-email: kislyuk@gmail.com
|
|
License: MIT License
|
|
Project-URL: Documentation, https://pyauth.github.io/pyotp
|
|
Project-URL: Source Code, https://github.com/pyauth/pyotp
|
|
Project-URL: Issue Tracker, https://github.com/pyauth/pyotp/issues
|
|
Project-URL: Change Log, https://github.com/pyauth/pyotp/blob/master/Changes.rst
|
|
Platform: MacOS X
|
|
Platform: Posix
|
|
Classifier: Intended Audience :: Developers
|
|
Classifier: License :: OSI Approved :: MIT License
|
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
Classifier: Operating System :: POSIX
|
|
Classifier: Programming Language :: Python
|
|
Classifier: Programming Language :: Python :: 3
|
|
Classifier: Programming Language :: Python :: 3.7
|
|
Classifier: Programming Language :: Python :: 3.8
|
|
Classifier: Programming Language :: Python :: 3.9
|
|
Classifier: Programming Language :: Python :: 3.10
|
|
Classifier: Programming Language :: Python :: 3.11
|
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
Requires-Python: >=3.7
|
|
License-File: LICENSE
|
|
Provides-Extra: test
|
|
Requires-Dist: coverage ; extra == 'test'
|
|
Requires-Dist: wheel ; extra == 'test'
|
|
Requires-Dist: ruff ; extra == 'test'
|
|
Requires-Dist: mypy ; extra == 'test'
|
|
|
|
PyOTP - The Python One-Time Password Library
|
|
============================================
|
|
|
|
PyOTP is a Python library for generating and verifying one-time passwords. It can be used to implement two-factor (2FA)
|
|
or multi-factor (MFA) authentication methods in web applications and in other systems that require users to log in.
|
|
|
|
Open MFA standards are defined in `RFC 4226 <https://tools.ietf.org/html/rfc4226>`_ (HOTP: An HMAC-Based One-Time
|
|
Password Algorithm) and in `RFC 6238 <https://tools.ietf.org/html/rfc6238>`_ (TOTP: Time-Based One-Time Password
|
|
Algorithm). PyOTP implements server-side support for both of these standards. Client-side support can be enabled by
|
|
sending authentication codes to users over SMS or email (HOTP) or, for TOTP, by instructing users to use `Google
|
|
Authenticator <https://en.wikipedia.org/wiki/Google_Authenticator>`_, `Authy <https://www.authy.com/>`_, or another
|
|
compatible app. Users can set up auth tokens in their apps easily by using their phone camera to scan `otpauth://
|
|
<https://github.com/google/google-authenticator/wiki/Key-Uri-Format>`_ QR codes provided by PyOTP.
|
|
|
|
Implementers should read and follow the `HOTP security requirements <https://tools.ietf.org/html/rfc4226#section-7>`_
|
|
and `TOTP security considerations <https://tools.ietf.org/html/rfc6238#section-5>`_ sections of the relevant RFCs. At
|
|
minimum, application implementers should follow this checklist:
|
|
|
|
- Ensure transport confidentiality by using HTTPS
|
|
- Ensure HOTP/TOTP secret confidentiality by storing secrets in a controlled access database
|
|
- Deny replay attacks by rejecting one-time passwords that have been used by the client (this requires storing the most
|
|
recently authenticated timestamp, OTP, or hash of the OTP in your database, and rejecting the OTP when a match is
|
|
seen)
|
|
- Throttle (rate limit) brute-force attacks against your application's login functionality (see RFC 4226, section 7.3)
|
|
- When implementing a "greenfield" application, consider supporting
|
|
`FIDO U2F <https://en.wikipedia.org/wiki/Universal_2nd_Factor>`_/`WebAuthn <https://www.w3.org/TR/webauthn/>`_ in
|
|
addition to HOTP/TOTP. U2F uses asymmetric cryptography to avoid using a shared secret design, which strengthens your
|
|
MFA solution against server-side attacks. Hardware U2F also sequesters the client secret in a dedicated single-purpose
|
|
device, which strengthens your clients against client-side attacks. And by automating scoping of credentials to
|
|
relying party IDs (application origin/domain names), U2F adds protection against phishing attacks. One implementation
|
|
of FIDO U2F/WebAuthn is PyOTP's sister project, `PyWARP <https://github.com/pyauth/pywarp>`_.
|
|
|
|
We also recommend that implementers read the
|
|
`OWASP Authentication Cheat Sheet
|
|
<https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md>`_ and
|
|
`NIST SP 800-63-3: Digital Authentication Guideline <https://pages.nist.gov/800-63-3/>`_ for a high level overview of
|
|
authentication best practices.
|
|
|
|
Quick overview of using One Time Passwords on your phone
|
|
--------------------------------------------------------
|
|
|
|
* OTPs involve a shared secret, stored both on the phone and the server
|
|
* OTPs can be generated on a phone without internet connectivity
|
|
* OTPs should always be used as a second factor of authentication (if your phone is lost, you account is still secured
|
|
with a password)
|
|
* Google Authenticator and other OTP client apps allow you to store multiple OTP secrets and provision those using a QR
|
|
Code
|
|
|
|
Installation
|
|
------------
|
|
::
|
|
|
|
pip install pyotp
|
|
|
|
Usage
|
|
-----
|
|
|
|
Time-based OTPs
|
|
~~~~~~~~~~~~~~~
|
|
::
|
|
|
|
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
|
|
|
|
Counter-based OTPs
|
|
~~~~~~~~~~~~~~~~~~
|
|
::
|
|
|
|
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
|
|
|
|
Generating a Secret Key
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
A helper function is provided to generate a 32-character base32 secret, compatible with Google Authenticator and other
|
|
OTP apps::
|
|
|
|
pyotp.random_base32()
|
|
|
|
Some applications want the secret key to be formatted as a hex-encoded string::
|
|
|
|
pyotp.random_hex() # returns a 40-character hex-encoded secret
|
|
|
|
Google Authenticator Compatible
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
PyOTP works with the Google Authenticator iPhone and Android app, as well as other OTP apps like Authy. PyOTP includes
|
|
the ability to generate provisioning URIs for use with the QR Code scanner built into these MFA client apps::
|
|
|
|
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'
|
|
|
|
This URL can then be rendered as a QR Code (for example, using https://github.com/soldair/node-qrcode) which can then be
|
|
scanned and added to the users list of OTP credentials.
|
|
|
|
Parsing these URLs is also supported::
|
|
|
|
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>
|
|
|
|
Working example
|
|
~~~~~~~~~~~~~~~
|
|
|
|
Scan the following barcode with your phone's OTP app (e.g. Google Authenticator):
|
|
|
|
.. image:: https://chart.apis.google.com/chart?cht=qr&chs=250x250&chl=otpauth%3A%2F%2Ftotp%2Falice%40google.com%3Fsecret%3DJBSWY3DPEHPK3PXP
|
|
|
|
Now run the following and compare the output::
|
|
|
|
import pyotp
|
|
totp = pyotp.TOTP("JBSWY3DPEHPK3PXP")
|
|
print("Current OTP:", totp.now())
|
|
|
|
Third-party contributions
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
The following third-party contributions are not described by a standard, not officially supported, and provided for
|
|
reference only:
|
|
|
|
* ``pyotp.contrib.Steam()``: An implementation of Steam TOTP. Uses the same API as `pyotp.TOTP()`.
|
|
|
|
Links
|
|
~~~~~
|
|
|
|
* `Project home page (GitHub) <https://github.com/pyauth/pyotp>`_
|
|
* `Documentation <https://pyauth.github.io/pyotp/>`_
|
|
* `Package distribution (PyPI) <https://pypi.python.org/pypi/pyotp>`_
|
|
* `Change log <https://github.com/pyauth/pyotp/blob/master/Changes.rst>`_
|
|
* `RFC 4226: HOTP: An HMAC-Based One-Time Password <https://tools.ietf.org/html/rfc4226>`_
|
|
* `RFC 6238: TOTP: Time-Based One-Time Password Algorithm <https://tools.ietf.org/html/rfc6238>`_
|
|
* `ROTP <https://github.com/mdp/rotp>`_ - Original Ruby OTP library by `Mark Percival <https://github.com/mdp>`_
|
|
* `OTPHP <https://github.com/lelag/otphp>`_ - PHP port of ROTP by `Le Lag <https://github.com/lelag>`_
|
|
* `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/>`_
|
|
|
|
For new applications:
|
|
|
|
* `WebAuthn <https://www.w3.org/TR/webauthn/>`_
|
|
* `PyWARP <https://github.com/pyauth/pywarp>`_
|
|
|
|
Versioning
|
|
~~~~~~~~~~
|
|
This package follows the `Semantic Versioning 2.0.0 <http://semver.org/>`_ standard. To control changes, it is
|
|
recommended that application developers pin the package version and manage it using `pip-tools
|
|
<https://github.com/jazzband/pip-tools>`_ or similar. For library developers, pinning the major version is
|
|
recommended.
|
|
|
|
.. image:: https://github.com/pyauth/pyotp/workflows/Python%20package/badge.svg
|
|
:target: https://github.com/pyauth/pyotp/actions
|
|
.. image:: https://img.shields.io/codecov/c/github/pyauth/pyotp/master.svg
|
|
:target: https://codecov.io/github/pyauth/pyotp?branch=master
|
|
.. image:: https://img.shields.io/pypi/v/pyotp.svg
|
|
:target: https://pypi.python.org/pypi/pyotp
|
|
.. image:: https://img.shields.io/pypi/l/pyotp.svg
|
|
:target: https://pypi.python.org/pypi/pyotp
|
|
.. image:: https://readthedocs.org/projects/pyotp/badge/?version=latest
|
|
:target: https://pyotp.readthedocs.io/
|