commit python-pyotp for openSUSE:Factory
Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pyotp for openSUSE:Factory checked in at 2023-12-15 21:48:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pyotp (Old) and /work/SRC/openSUSE:Factory/.python-pyotp.new.25432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-pyotp" Fri Dec 15 21:48:30 2023 rev:7 rq:1133203 version:2.9.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pyotp/python-pyotp.changes 2023-01-03 15:05:39.734613827 +0100 +++ /work/SRC/openSUSE:Factory/.python-pyotp.new.25432/python-pyotp.changes 2023-12-15 21:48:43.521330722 +0100 @@ -1,0 +2,7 @@ +Thu Dec 14 21:30:56 UTC 2023 - Dirk Müller <dmueller@suse.com> + +- update to 2.9.0: + * Add `parse_uri()` support for Steam TOTP (#153) + * Test and documentation improvements + +------------------------------------------------------------------- Old: ---- pyotp-2.8.0.tar.gz New: ---- pyotp-2.9.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pyotp.spec ++++++ --- /var/tmp/diff_new_pack.HieXdl/_old 2023-12-15 21:48:44.645372080 +0100 +++ /var/tmp/diff_new_pack.HieXdl/_new 2023-12-15 21:48:44.661372668 +0100 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-pyotp -Version: 2.8.0 +Version: 2.9.0 Release: 0 Summary: Python One Time Password Library License: MIT ++++++ pyotp-2.8.0.tar.gz -> pyotp-2.9.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/PKG-INFO new/pyotp-2.9.0/PKG-INFO --- old/pyotp-2.8.0/PKG-INFO 2022-12-14 04:54:21.049833300 +0100 +++ new/pyotp-2.9.0/PKG-INFO 2023-07-28 01:40:52.158836000 +0200 @@ -1,11 +1,15 @@ Metadata-Version: 2.1 Name: pyotp -Version: 2.8.0 +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 @@ -14,13 +18,14 @@ Classifier: Operating System :: POSIX Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.6 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 +Provides-Extra: test License-File: LICENSE PyOTP - The Python One-Time Password Library @@ -43,19 +48,21 @@ - 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) +- 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>`_. + 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 +`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. @@ -64,8 +71,10 @@ * 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 +* 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 ------------ @@ -108,7 +117,8 @@ Generating a Secret Key ~~~~~~~~~~~~~~~~~~~~~~~ -A helper function is provided to generate a 32-character base32 secret, compatible with Google Authenticator and other OTP apps:: +A helper function is provided to generate a 32-character base32 secret, compatible with Google Authenticator and other +OTP apps:: pyotp.random_base32() @@ -119,8 +129,8 @@ 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 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') @@ -130,8 +140,8 @@ >>> '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. +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:: @@ -156,6 +166,13 @@ 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 ~~~~~ @@ -175,6 +192,13 @@ * `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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/README.rst new/pyotp-2.9.0/README.rst --- old/pyotp-2.8.0/README.rst 2022-12-14 04:34:30.000000000 +0100 +++ new/pyotp-2.9.0/README.rst 2023-06-16 02:22:25.000000000 +0200 @@ -18,19 +18,21 @@ - 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) +- 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>`_. + 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 +`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. @@ -39,8 +41,10 @@ * 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 +* 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 ------------ @@ -83,7 +87,8 @@ Generating a Secret Key ~~~~~~~~~~~~~~~~~~~~~~~ -A helper function is provided to generate a 32-character base32 secret, compatible with Google Authenticator and other OTP apps:: +A helper function is provided to generate a 32-character base32 secret, compatible with Google Authenticator and other +OTP apps:: pyotp.random_base32() @@ -94,8 +99,8 @@ 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 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') @@ -105,8 +110,8 @@ >>> '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. +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:: @@ -131,6 +136,13 @@ 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 ~~~~~ @@ -150,6 +162,13 @@ * `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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/pyproject.toml new/pyotp-2.9.0/pyproject.toml --- old/pyotp-2.8.0/pyproject.toml 2022-09-11 20:53:33.000000000 +0200 +++ new/pyotp-2.9.0/pyproject.toml 2023-06-16 02:22:25.000000000 +0200 @@ -1,5 +1,9 @@ [tool.black] line-length = 120 + [tool.isort] profile = "black" line_length = 120 + +[tool.ruff] +line-length = 120 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/setup.cfg new/pyotp-2.9.0/setup.cfg --- old/pyotp-2.8.0/setup.cfg 2022-12-14 04:54:21.051077800 +0100 +++ new/pyotp-2.9.0/setup.cfg 2023-07-28 01:40:52.160089700 +0200 @@ -1,7 +1,3 @@ -[flake8] -max-line-length = 120 -extend-ignore = E203 - [egg_info] tag_build = tag_date = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/setup.py new/pyotp-2.9.0/setup.py --- old/pyotp-2.8.0/setup.py 2022-12-14 04:53:16.000000000 +0100 +++ new/pyotp-2.9.0/setup.py 2023-07-28 01:38:36.000000000 +0200 @@ -4,8 +4,14 @@ setup( name="pyotp", - version="2.8.0", + version="2.9.0", url="https://github.com/pyotp/pyotp", + project_urls={ + "Documentation": "https://pyauth.github.io/pyotp", + "Source Code": "https://github.com/pyauth/pyotp", + "Issue Tracker": "https://github.com/pyauth/pyotp/issues", + "Change Log": "https://github.com/pyauth/pyotp/blob/master/Changes.rst", + }, license="MIT License", author="PyOTP contributors", author_email="kislyuk@gmail.com", @@ -13,6 +19,9 @@ long_description=open("README.rst").read(), python_requires=">=3.7", install_requires=[], + extras_require={ + "test": ["coverage", "wheel", "ruff", "mypy"], + }, packages=["pyotp", "pyotp.contrib"], package_dir={"": "src"}, package_data={"pyotp": ["py.typed"]}, @@ -26,11 +35,11 @@ "Operating System :: POSIX", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Topic :: Software Development :: Libraries :: Python Modules", ], ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/src/pyotp/__init__.py new/pyotp-2.9.0/src/pyotp/__init__.py --- old/pyotp-2.8.0/src/pyotp/__init__.py 2022-12-14 04:51:41.000000000 +0100 +++ new/pyotp-2.9.0/src/pyotp/__init__.py 2023-07-28 01:37:40.000000000 +0200 @@ -40,6 +40,12 @@ # Secret (to be filled in later) secret = None + # Encoder (to be filled in later) + encoder = None + + # Digits (to be filled in later) + digits = None + # Data we'll parse to the correct constructor otp_data: Dict[str, Any] = {} @@ -74,10 +80,10 @@ otp_data["digest"] = hashlib.sha512 else: raise ValueError("Invalid value for algorithm, must be SHA1, SHA256 or SHA512") + elif key == "encoder": + encoder = value elif key == "digits": digits = int(value) - if digits not in [6, 7, 8]: - raise ValueError("Digits may only be 6, 7, or 8") otp_data["digits"] = digits elif key == "period": otp_data["interval"] = int(value) @@ -85,11 +91,17 @@ otp_data["initial_count"] = int(value) elif key != "image": raise ValueError("{} is not a valid parameter".format(key)) - + + if encoder != "steam": + if digits is not None and digits not in [6, 7, 8]: + raise ValueError("Digits may only be 6, 7, or 8") + if not secret: raise ValueError("No secret found in URI") # Create objects + if encoder == "steam": + return contrib.Steam(secret, **otp_data) if parsed_uri.netloc == "totp": return TOTP(secret, **otp_data) elif parsed_uri.netloc == "hotp": diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/src/pyotp/contrib/steam.py new/pyotp-2.9.0/src/pyotp/contrib/steam.py --- old/pyotp-2.8.0/src/pyotp/contrib/steam.py 2022-09-11 20:53:33.000000000 +0200 +++ new/pyotp-2.9.0/src/pyotp/contrib/steam.py 2023-07-28 01:37:40.000000000 +0200 @@ -12,7 +12,14 @@ Steam's custom TOTP. Subclass of `pyotp.totp.TOTP`. """ - def __init__(self, s: str, name: Optional[str] = None, issuer: Optional[str] = None, interval: int = 30) -> None: + def __init__( + self, + s: str, + name: Optional[str] = None, + issuer: Optional[str] = None, + interval: int = 30, + digits: int = 5 + ) -> None: """ :param s: secret in base32 format :param interval: the time interval in seconds for OTP. This defaults to 30. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/src/pyotp.egg-info/PKG-INFO new/pyotp-2.9.0/src/pyotp.egg-info/PKG-INFO --- old/pyotp-2.8.0/src/pyotp.egg-info/PKG-INFO 2022-12-14 04:54:21.000000000 +0100 +++ new/pyotp-2.9.0/src/pyotp.egg-info/PKG-INFO 2023-07-28 01:40:52.000000000 +0200 @@ -1,11 +1,15 @@ Metadata-Version: 2.1 Name: pyotp -Version: 2.8.0 +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 @@ -14,13 +18,14 @@ Classifier: Operating System :: POSIX Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.6 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 +Provides-Extra: test License-File: LICENSE PyOTP - The Python One-Time Password Library @@ -43,19 +48,21 @@ - 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) +- 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>`_. + 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 +`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. @@ -64,8 +71,10 @@ * 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 +* 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 ------------ @@ -108,7 +117,8 @@ Generating a Secret Key ~~~~~~~~~~~~~~~~~~~~~~~ -A helper function is provided to generate a 32-character base32 secret, compatible with Google Authenticator and other OTP apps:: +A helper function is provided to generate a 32-character base32 secret, compatible with Google Authenticator and other +OTP apps:: pyotp.random_base32() @@ -119,8 +129,8 @@ 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 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') @@ -130,8 +140,8 @@ >>> '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. +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:: @@ -156,6 +166,13 @@ 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 ~~~~~ @@ -175,6 +192,13 @@ * `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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/src/pyotp.egg-info/SOURCES.txt new/pyotp-2.9.0/src/pyotp.egg-info/SOURCES.txt --- old/pyotp-2.8.0/src/pyotp.egg-info/SOURCES.txt 2022-12-14 04:54:21.000000000 +0100 +++ new/pyotp-2.9.0/src/pyotp.egg-info/SOURCES.txt 2023-07-28 01:40:52.000000000 +0200 @@ -2,7 +2,6 @@ MANIFEST.in README.rst pyproject.toml -setup.cfg setup.py test.py src/pyotp/__init__.py @@ -16,6 +15,7 @@ src/pyotp.egg-info/SOURCES.txt src/pyotp.egg-info/dependency_links.txt src/pyotp.egg-info/not-zip-safe +src/pyotp.egg-info/requires.txt src/pyotp.egg-info/top_level.txt src/pyotp/contrib/__init__.py src/pyotp/contrib/steam.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/src/pyotp.egg-info/requires.txt new/pyotp-2.9.0/src/pyotp.egg-info/requires.txt --- old/pyotp-2.8.0/src/pyotp.egg-info/requires.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/pyotp-2.9.0/src/pyotp.egg-info/requires.txt 2023-07-28 01:40:52.000000000 +0200 @@ -0,0 +1,6 @@ + +[test] +coverage +wheel +ruff +mypy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyotp-2.8.0/test.py new/pyotp-2.9.0/test.py --- old/pyotp-2.8.0/test.py 2022-09-11 20:53:33.000000000 +0200 +++ new/pyotp-2.9.0/test.py 2023-07-28 01:37:40.000000000 +0200 @@ -364,6 +364,13 @@ with self.assertRaises(ValueError) as cm: pyotp.parse_uri("otpauth://totp?algorithm=aes") self.assertEqual("Invalid value for algorithm, must be SHA1, SHA256 or SHA512", str(cm.exception)) + + def test_parse_steam(self): + otp = pyotp.parse_uri("otpauth://totp/Steam:?secret=SOME_SECRET&encoder=steam") + self.assertEqual(type(otp), pyotp.contrib.Steam) + + otp = pyotp.parse_uri("otpauth://totp/Steam:?secret=SOME_SECRET") + self.assertNotEqual(type(otp), pyotp.contrib.Steam) @unittest.skipIf(sys.version_info < (3, 6), "Skipping test that requires deterministic dict key enumeration") def test_algorithms(self): @@ -420,6 +427,20 @@ otp = pyotp.parse_uri(otp.provisioning_uri(name="n", issuer_name="i", image="https://test.net/test.png")) self.assertEqual(hashlib.sha512, otp.digest) + otp = pyotp.parse_uri("otpauth://totp/Steam:?secret=FMXNK4QEGKVPULRTADY6JIDK5VHUBGZW&encoder=steam") + self.assertEqual(type(otp), pyotp.contrib.Steam) + self.assertEqual(otp.at(0), "C5V56") + self.assertEqual(otp.at(30), "QJY8Y") + self.assertEqual(otp.at(60), "R3WQY") + self.assertEqual(otp.at(90), "JG3T3") + + # period and digits should be ignored + otp = pyotp.parse_uri("otpauth://totp/Steam:?secret=FMXNK4QEGKVPULRTADY6JIDK5VHUBGZW&period=15&digits=7&encoder=steam") + self.assertEqual(type(otp), pyotp.contrib.Steam) + self.assertEqual(otp.at(0), "C5V56") + self.assertEqual(otp.at(30), "QJY8Y") + self.assertEqual(otp.at(60), "R3WQY") + self.assertEqual(otp.at(90), "JG3T3") class Timecop(object): """
participants (1)
-
Source-Sync