PyOTP 2.7.0__tar.gz → 2.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyotp-2.7.0/src/pyotp.egg-info → pyotp-2.8.0}/PKG-INFO +8 -3
- {pyotp-2.7.0 → pyotp-2.8.0}/README.rst +6 -1
- {pyotp-2.7.0 → pyotp-2.8.0}/setup.py +2 -2
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp/__init__.py +1 -1
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp/hotp.py +5 -2
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp/otp.py +4 -5
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp/totp.py +8 -3
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp/utils.py +1 -1
- {pyotp-2.7.0 → pyotp-2.8.0/src/pyotp.egg-info}/PKG-INFO +8 -3
- {pyotp-2.7.0 → pyotp-2.8.0}/LICENSE +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/MANIFEST.in +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/pyproject.toml +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/setup.cfg +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp/compat.py +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp/contrib/__init__.py +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp/contrib/steam.py +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp/py.typed +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp.egg-info/SOURCES.txt +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp.egg-info/dependency_links.txt +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp.egg-info/not-zip-safe +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/src/pyotp.egg-info/top_level.txt +0 -0
- {pyotp-2.7.0 → pyotp-2.8.0}/test.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyotp
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0
|
|
4
4
|
Summary: Python One Time Password Library
|
|
5
5
|
Home-page: https://github.com/pyotp/pyotp
|
|
6
6
|
Author: PyOTP contributors
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.9
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.10
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
-
Requires-Python: >=3.
|
|
23
|
+
Requires-Python: >=3.7
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
|
|
26
26
|
PyOTP - The Python One-Time Password Library
|
|
@@ -45,7 +45,7 @@ minimum, application implementers should follow this checklist:
|
|
|
45
45
|
- Ensure HOTP/TOTP secret confidentiality by storing secrets in a controlled access database
|
|
46
46
|
- Deny replay attacks by rejecting one-time passwords that have been used by the client (this requires storing the most
|
|
47
47
|
recently authenticated timestamp, OTP, or hash of the OTP in your database, and rejecting the OTP when a match is seen)
|
|
48
|
-
- Throttle (rate limit) brute-force attacks against your application's login functionality
|
|
48
|
+
- Throttle (rate limit) brute-force attacks against your application's login functionality (see RFC 4226, section 7.3)
|
|
49
49
|
- When implementing a "greenfield" application, consider supporting
|
|
50
50
|
`FIDO U2F <https://en.wikipedia.org/wiki/Universal_2nd_Factor>`_/`WebAuthn <https://www.w3.org/TR/webauthn/>`_ in
|
|
51
51
|
addition to HOTP/TOTP. U2F uses asymmetric cryptography to avoid using a shared secret design, which strengthens your
|
|
@@ -80,6 +80,9 @@ Time-based OTPs
|
|
|
80
80
|
~~~~~~~~~~~~~~~
|
|
81
81
|
::
|
|
82
82
|
|
|
83
|
+
import pyotp
|
|
84
|
+
import time
|
|
85
|
+
|
|
83
86
|
totp = pyotp.TOTP('base32secret3232')
|
|
84
87
|
totp.now() # => '492039'
|
|
85
88
|
|
|
@@ -92,6 +95,8 @@ Counter-based OTPs
|
|
|
92
95
|
~~~~~~~~~~~~~~~~~~
|
|
93
96
|
::
|
|
94
97
|
|
|
98
|
+
import pyotp
|
|
99
|
+
|
|
95
100
|
hotp = pyotp.HOTP('base32secret3232')
|
|
96
101
|
hotp.at(0) # => '260182'
|
|
97
102
|
hotp.at(1) # => '055283'
|
|
@@ -20,7 +20,7 @@ minimum, application implementers should follow this checklist:
|
|
|
20
20
|
- Ensure HOTP/TOTP secret confidentiality by storing secrets in a controlled access database
|
|
21
21
|
- Deny replay attacks by rejecting one-time passwords that have been used by the client (this requires storing the most
|
|
22
22
|
recently authenticated timestamp, OTP, or hash of the OTP in your database, and rejecting the OTP when a match is seen)
|
|
23
|
-
- Throttle (rate limit) brute-force attacks against your application's login functionality
|
|
23
|
+
- Throttle (rate limit) brute-force attacks against your application's login functionality (see RFC 4226, section 7.3)
|
|
24
24
|
- When implementing a "greenfield" application, consider supporting
|
|
25
25
|
`FIDO U2F <https://en.wikipedia.org/wiki/Universal_2nd_Factor>`_/`WebAuthn <https://www.w3.org/TR/webauthn/>`_ in
|
|
26
26
|
addition to HOTP/TOTP. U2F uses asymmetric cryptography to avoid using a shared secret design, which strengthens your
|
|
@@ -55,6 +55,9 @@ Time-based OTPs
|
|
|
55
55
|
~~~~~~~~~~~~~~~
|
|
56
56
|
::
|
|
57
57
|
|
|
58
|
+
import pyotp
|
|
59
|
+
import time
|
|
60
|
+
|
|
58
61
|
totp = pyotp.TOTP('base32secret3232')
|
|
59
62
|
totp.now() # => '492039'
|
|
60
63
|
|
|
@@ -67,6 +70,8 @@ Counter-based OTPs
|
|
|
67
70
|
~~~~~~~~~~~~~~~~~~
|
|
68
71
|
::
|
|
69
72
|
|
|
73
|
+
import pyotp
|
|
74
|
+
|
|
70
75
|
hotp = pyotp.HOTP('base32secret3232')
|
|
71
76
|
hotp.at(0) # => '260182'
|
|
72
77
|
hotp.at(1) # => '055283'
|
|
@@ -4,14 +4,14 @@ from setuptools import setup
|
|
|
4
4
|
|
|
5
5
|
setup(
|
|
6
6
|
name="pyotp",
|
|
7
|
-
version="2.
|
|
7
|
+
version="2.8.0",
|
|
8
8
|
url="https://github.com/pyotp/pyotp",
|
|
9
9
|
license="MIT License",
|
|
10
10
|
author="PyOTP contributors",
|
|
11
11
|
author_email="kislyuk@gmail.com",
|
|
12
12
|
description="Python One Time Password Library",
|
|
13
13
|
long_description=open("README.rst").read(),
|
|
14
|
-
python_requires=">=3.
|
|
14
|
+
python_requires=">=3.7",
|
|
15
15
|
install_requires=[],
|
|
16
16
|
packages=["pyotp", "pyotp.contrib"],
|
|
17
17
|
package_dir={"": "src"},
|
|
@@ -14,7 +14,7 @@ class HOTP(OTP):
|
|
|
14
14
|
self,
|
|
15
15
|
s: str,
|
|
16
16
|
digits: int = 6,
|
|
17
|
-
digest: Any =
|
|
17
|
+
digest: Any = None,
|
|
18
18
|
name: Optional[str] = None,
|
|
19
19
|
issuer: Optional[str] = None,
|
|
20
20
|
initial_count: int = 0,
|
|
@@ -23,10 +23,13 @@ class HOTP(OTP):
|
|
|
23
23
|
:param s: secret in base32 format
|
|
24
24
|
:param initial_count: starting HMAC counter value, defaults to 0
|
|
25
25
|
:param digits: number of integers in the OTP. Some apps expect this to be 6 digits, others support more.
|
|
26
|
-
:param digest: digest function to use in the HMAC (expected to be
|
|
26
|
+
:param digest: digest function to use in the HMAC (expected to be SHA1)
|
|
27
27
|
:param name: account name
|
|
28
28
|
:param issuer: issuer
|
|
29
29
|
"""
|
|
30
|
+
if digest is None:
|
|
31
|
+
digest = hashlib.sha1
|
|
32
|
+
|
|
30
33
|
self.initial_count = initial_count
|
|
31
34
|
super().__init__(s=s, digits=digits, digest=digest, name=name, issuer=issuer)
|
|
32
35
|
|
|
@@ -18,6 +18,8 @@ class OTP(object):
|
|
|
18
18
|
issuer: Optional[str] = None,
|
|
19
19
|
) -> None:
|
|
20
20
|
self.digits = digits
|
|
21
|
+
if digits > 10:
|
|
22
|
+
raise ValueError("digits must be no greater than 10")
|
|
21
23
|
self.digest = digest
|
|
22
24
|
self.secret = s
|
|
23
25
|
self.name = name or "Secret"
|
|
@@ -39,11 +41,8 @@ class OTP(object):
|
|
|
39
41
|
| (hmac_hash[offset + 2] & 0xFF) << 8
|
|
40
42
|
| (hmac_hash[offset + 3] & 0xFF)
|
|
41
43
|
)
|
|
42
|
-
str_code = str(code % 10**self.digits)
|
|
43
|
-
|
|
44
|
-
str_code = "0" + str_code
|
|
45
|
-
|
|
46
|
-
return str_code
|
|
44
|
+
str_code = str(10_000_000_000 + (code % 10**self.digits))
|
|
45
|
+
return str_code[-self.digits :]
|
|
47
46
|
|
|
48
47
|
def byte_secret(self) -> bytes:
|
|
49
48
|
secret = self.secret
|
|
@@ -17,7 +17,7 @@ class TOTP(OTP):
|
|
|
17
17
|
self,
|
|
18
18
|
s: str,
|
|
19
19
|
digits: int = 6,
|
|
20
|
-
digest: Any =
|
|
20
|
+
digest: Any = None,
|
|
21
21
|
name: Optional[str] = None,
|
|
22
22
|
issuer: Optional[str] = None,
|
|
23
23
|
interval: int = 30,
|
|
@@ -26,10 +26,13 @@ class TOTP(OTP):
|
|
|
26
26
|
:param s: secret in base32 format
|
|
27
27
|
:param interval: the time interval in seconds for OTP. This defaults to 30.
|
|
28
28
|
:param digits: number of integers in the OTP. Some apps expect this to be 6 digits, others support more.
|
|
29
|
-
:param digest: digest function to use in the HMAC (expected to be
|
|
29
|
+
:param digest: digest function to use in the HMAC (expected to be SHA1)
|
|
30
30
|
:param name: account name
|
|
31
31
|
:param issuer: issuer
|
|
32
32
|
"""
|
|
33
|
+
if digest is None:
|
|
34
|
+
digest = hashlib.sha1
|
|
35
|
+
|
|
33
36
|
self.interval = interval
|
|
34
37
|
super().__init__(s=s, digits=digits, digest=digest, name=name, issuer=issuer)
|
|
35
38
|
|
|
@@ -37,7 +40,9 @@ class TOTP(OTP):
|
|
|
37
40
|
"""
|
|
38
41
|
Accepts either a Unix timestamp integer or a datetime object.
|
|
39
42
|
|
|
40
|
-
To get the time until the next timecode change (seconds until the current OTP expires), use this instead
|
|
43
|
+
To get the time until the next timecode change (seconds until the current OTP expires), use this instead:
|
|
44
|
+
|
|
45
|
+
.. code:: python
|
|
41
46
|
|
|
42
47
|
totp = pyotp.TOTP(...)
|
|
43
48
|
time_remaining = totp.interval - datetime.datetime.now().timestamp() % totp.interval
|
|
@@ -49,7 +49,7 @@ def build_uri(
|
|
|
49
49
|
otp_type = "hotp" if is_initial_count_present else "totp"
|
|
50
50
|
base_uri = "otpauth://{0}/{1}?{2}"
|
|
51
51
|
|
|
52
|
-
url_args
|
|
52
|
+
url_args: Dict[str, Union[None, int, str]] = {"secret": secret}
|
|
53
53
|
|
|
54
54
|
label = quote(name)
|
|
55
55
|
if issuer is not None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyotp
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0
|
|
4
4
|
Summary: Python One Time Password Library
|
|
5
5
|
Home-page: https://github.com/pyotp/pyotp
|
|
6
6
|
Author: PyOTP contributors
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.9
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.10
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
-
Requires-Python: >=3.
|
|
23
|
+
Requires-Python: >=3.7
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
|
|
26
26
|
PyOTP - The Python One-Time Password Library
|
|
@@ -45,7 +45,7 @@ minimum, application implementers should follow this checklist:
|
|
|
45
45
|
- Ensure HOTP/TOTP secret confidentiality by storing secrets in a controlled access database
|
|
46
46
|
- Deny replay attacks by rejecting one-time passwords that have been used by the client (this requires storing the most
|
|
47
47
|
recently authenticated timestamp, OTP, or hash of the OTP in your database, and rejecting the OTP when a match is seen)
|
|
48
|
-
- Throttle (rate limit) brute-force attacks against your application's login functionality
|
|
48
|
+
- Throttle (rate limit) brute-force attacks against your application's login functionality (see RFC 4226, section 7.3)
|
|
49
49
|
- When implementing a "greenfield" application, consider supporting
|
|
50
50
|
`FIDO U2F <https://en.wikipedia.org/wiki/Universal_2nd_Factor>`_/`WebAuthn <https://www.w3.org/TR/webauthn/>`_ in
|
|
51
51
|
addition to HOTP/TOTP. U2F uses asymmetric cryptography to avoid using a shared secret design, which strengthens your
|
|
@@ -80,6 +80,9 @@ Time-based OTPs
|
|
|
80
80
|
~~~~~~~~~~~~~~~
|
|
81
81
|
::
|
|
82
82
|
|
|
83
|
+
import pyotp
|
|
84
|
+
import time
|
|
85
|
+
|
|
83
86
|
totp = pyotp.TOTP('base32secret3232')
|
|
84
87
|
totp.now() # => '492039'
|
|
85
88
|
|
|
@@ -92,6 +95,8 @@ Counter-based OTPs
|
|
|
92
95
|
~~~~~~~~~~~~~~~~~~
|
|
93
96
|
::
|
|
94
97
|
|
|
98
|
+
import pyotp
|
|
99
|
+
|
|
95
100
|
hotp = pyotp.HOTP('base32secret3232')
|
|
96
101
|
hotp.at(0) # => '260182'
|
|
97
102
|
hotp.at(1) # => '055283'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|