PyOTP 2.2.6__tar.gz → 2.2.8__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.2.6 → pyotp-2.2.8}/LICENSE +3 -2
- {pyotp-2.2.6/src/pyotp.egg-info → pyotp-2.2.8}/PKG-INFO +42 -15
- {pyotp-2.2.6 → pyotp-2.2.8}/README.rst +36 -11
- {pyotp-2.2.6 → pyotp-2.2.8}/setup.cfg +1 -1
- {pyotp-2.2.6 → pyotp-2.2.8}/setup.py +6 -4
- {pyotp-2.2.6 → pyotp-2.2.8}/src/pyotp/__init__.py +10 -4
- {pyotp-2.2.6 → pyotp-2.2.8}/src/pyotp/hotp.py +1 -1
- {pyotp-2.2.6 → pyotp-2.2.8}/src/pyotp/utils.py +2 -2
- {pyotp-2.2.6 → pyotp-2.2.8/src/pyotp.egg-info}/PKG-INFO +42 -15
- {pyotp-2.2.6 → pyotp-2.2.8}/test.py +3 -0
- {pyotp-2.2.6 → pyotp-2.2.8}/MANIFEST.in +0 -0
- {pyotp-2.2.6 → pyotp-2.2.8}/requirements.txt +0 -0
- {pyotp-2.2.6 → pyotp-2.2.8}/src/pyotp/compat.py +0 -0
- {pyotp-2.2.6 → pyotp-2.2.8}/src/pyotp/otp.py +0 -0
- {pyotp-2.2.6 → pyotp-2.2.8}/src/pyotp/totp.py +0 -0
- {pyotp-2.2.6 → pyotp-2.2.8}/src/pyotp.egg-info/SOURCES.txt +0 -0
- {pyotp-2.2.6 → pyotp-2.2.8}/src/pyotp.egg-info/dependency_links.txt +0 -0
- {pyotp-2.2.6 → pyotp-2.2.8}/src/pyotp.egg-info/not-zip-safe +0 -0
- {pyotp-2.2.6 → pyotp-2.2.8}/src/pyotp.egg-info/top_level.txt +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
Copyright (C) 2011-
|
|
2
|
-
Nathan Reynolds <email@nreynolds.co.uk>,
|
|
1
|
+
Copyright (C) 2011-2017 Mark Percival <m@mdp.im>,
|
|
2
|
+
Nathan Reynolds <email@nreynolds.co.uk>, Andrey Kislyuk <kislyuk@gmail.com>,
|
|
3
|
+
and PyOTP contributors
|
|
3
4
|
|
|
4
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 1.1
|
|
2
2
|
Name: pyotp
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.8
|
|
4
4
|
Summary: Python One Time Password Library
|
|
5
5
|
Home-page: https://github.com/pyotp/pyotp
|
|
6
6
|
Author: PyOTP contributors
|
|
7
7
|
Author-email: kislyuk@gmail.com
|
|
8
|
-
License:
|
|
8
|
+
License: MIT License
|
|
9
9
|
Description: PyOTP - The Python One-Time Password Library
|
|
10
10
|
============================================
|
|
11
11
|
|
|
@@ -20,7 +20,27 @@ Description: PyOTP - The Python One-Time Password Library
|
|
|
20
20
|
compatible app. Users can set up auth tokens in their apps easily by using their phone camera to scan `otpauth://
|
|
21
21
|
<https://github.com/google/google-authenticator/wiki/Key-Uri-Format>`_ QR codes provided by PyOTP.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Implementers should read and follow the `HOTP security requirements <https://tools.ietf.org/html/rfc4226#section-7>`_
|
|
24
|
+
and `TOTP security considerations <https://tools.ietf.org/html/rfc6238#section-5>`_ sections of the relevant RFCs. At
|
|
25
|
+
minimum, application implementers should follow this checklist:
|
|
26
|
+
|
|
27
|
+
- Ensure transport confidentiality by using HTTPS
|
|
28
|
+
- Ensure HOTP/TOTP secret confidentiality by storing secrets in a controlled access database
|
|
29
|
+
- Deny replay attacks by rejecting one-time passwords that have been used by the client (this requires storing the most
|
|
30
|
+
recently authenticated timestamp, OTP, or hash of the OTP in your database, and rejecting the OTP when a match is seen)
|
|
31
|
+
- Throttle brute-force attacks against your application's login functionality
|
|
32
|
+
- When implementing a "greenfield" application, consider supporting
|
|
33
|
+
`FIDO U2F <https://en.wikipedia.org/wiki/Universal_2nd_Factor>`_/`WebAuthn <https://www.w3.org/TR/webauthn/>`_ in
|
|
34
|
+
addition to HOTP/TOTP. U2F uses asymmetric cryptography to avoid using a shared secret design, which strengthens your
|
|
35
|
+
MFA solution against server-side attacks. Hardware U2F also sequesters the client secret in a dedicated single-purpose
|
|
36
|
+
device, which strengthens your clients against client-side attacks. And by automating scoping of credentials to
|
|
37
|
+
relying party IDs (application origin/domain names), U2F adds protection against phishing attacks. One implementation of
|
|
38
|
+
FIDO U2F/WebAuthn is PyOTP's sister project, `PyWARP <https://github.com/pyauth/pywarp>`_.
|
|
39
|
+
|
|
40
|
+
We also recommend that implementers read the
|
|
41
|
+
`OWASP Authentication Cheat Sheet <https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md>`_ and
|
|
42
|
+
`NIST SP 800-63-3: Digital Authentication Guideline <https://pages.nist.gov/800-63-3/>`_ for a high level overview of
|
|
43
|
+
authentication best practices.
|
|
24
44
|
|
|
25
45
|
Quick overview of using One Time Passwords on your phone
|
|
26
46
|
--------------------------------------------------------
|
|
@@ -44,25 +64,25 @@ Description: PyOTP - The Python One-Time Password Library
|
|
|
44
64
|
::
|
|
45
65
|
|
|
46
66
|
totp = pyotp.TOTP('base32secret3232')
|
|
47
|
-
totp.now() # => 492039
|
|
67
|
+
totp.now() # => '492039'
|
|
48
68
|
|
|
49
69
|
# OTP verified for current time
|
|
50
|
-
totp.verify(492039) # => True
|
|
70
|
+
totp.verify('492039') # => True
|
|
51
71
|
time.sleep(30)
|
|
52
|
-
totp.verify(492039) # => False
|
|
72
|
+
totp.verify('492039') # => False
|
|
53
73
|
|
|
54
74
|
Counter-based OTPs
|
|
55
75
|
~~~~~~~~~~~~~~~~~~
|
|
56
76
|
::
|
|
57
77
|
|
|
58
78
|
hotp = pyotp.HOTP('base32secret3232')
|
|
59
|
-
hotp.at(0) # => 260182
|
|
60
|
-
hotp.at(1) # =>
|
|
61
|
-
hotp.at(1401) # => 316439
|
|
79
|
+
hotp.at(0) # => '260182'
|
|
80
|
+
hotp.at(1) # => '055283'
|
|
81
|
+
hotp.at(1401) # => '316439'
|
|
62
82
|
|
|
63
83
|
# OTP verified with a counter
|
|
64
|
-
hotp.verify(316439, 1401) # => True
|
|
65
|
-
hotp.verify(316439, 1402) # => False
|
|
84
|
+
hotp.verify('316439', 1401) # => True
|
|
85
|
+
hotp.verify('316439', 1402) # => False
|
|
66
86
|
|
|
67
87
|
Generating a base32 Secret Key
|
|
68
88
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -92,7 +112,7 @@ Description: PyOTP - The Python One-Time Password Library
|
|
|
92
112
|
|
|
93
113
|
Scan the following barcode with your phone's OTP app (e.g. Google Authenticator):
|
|
94
114
|
|
|
95
|
-
.. image::
|
|
115
|
+
.. image:: https://chart.apis.google.com/chart?cht=qr&chs=250x250&chl=otpauth%3A%2F%2Ftotp%2Falice%40google.com%3Fsecret%3DJBSWY3DPEHPK3PXP
|
|
96
116
|
|
|
97
117
|
Now run the following and compare the output::
|
|
98
118
|
|
|
@@ -111,9 +131,14 @@ Description: PyOTP - The Python One-Time Password Library
|
|
|
111
131
|
* `RFC 6238: TOTP: Time-Based One-Time Password Algorithm <https://tools.ietf.org/html/rfc6238>`_
|
|
112
132
|
* `ROTP <https://github.com/mdp/rotp>`_ - Original Ruby OTP library by `Mark Percival <https://github.com/mdp>`_
|
|
113
133
|
* `OTPHP <https://github.com/lelag/otphp>`_ - PHP port of ROTP by `Le Lag <https://github.com/lelag>`_
|
|
114
|
-
* `OWASP Authentication Cheat Sheet <https://
|
|
134
|
+
* `OWASP Authentication Cheat Sheet <https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md>`_
|
|
115
135
|
* `NIST SP 800-63-3: Digital Authentication Guideline <https://pages.nist.gov/800-63-3/>`_
|
|
116
136
|
|
|
137
|
+
For new applications:
|
|
138
|
+
|
|
139
|
+
* `WebAuthn <https://www.w3.org/TR/webauthn/>`_
|
|
140
|
+
* `PyWARP <https://github.com/pyauth/pywarp>`_
|
|
141
|
+
|
|
117
142
|
.. image:: https://img.shields.io/travis/pyotp/pyotp.svg
|
|
118
143
|
:target: https://travis-ci.org/pyotp/pyotp
|
|
119
144
|
.. image:: https://img.shields.io/codecov/c/github/pyotp/pyotp/master.svg
|
|
@@ -128,11 +153,13 @@ Description: PyOTP - The Python One-Time Password Library
|
|
|
128
153
|
Platform: MacOS X
|
|
129
154
|
Platform: Posix
|
|
130
155
|
Classifier: Intended Audience :: Developers
|
|
131
|
-
Classifier: License :: OSI Approved ::
|
|
156
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
132
157
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
133
158
|
Classifier: Operating System :: POSIX
|
|
134
159
|
Classifier: Programming Language :: Python
|
|
135
160
|
Classifier: Programming Language :: Python :: 2.7
|
|
136
|
-
Classifier: Programming Language :: Python :: 3.3
|
|
137
161
|
Classifier: Programming Language :: Python :: 3.4
|
|
162
|
+
Classifier: Programming Language :: Python :: 3.5
|
|
163
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
164
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
138
165
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
@@ -12,7 +12,27 @@ Authenticator <https://en.wikipedia.org/wiki/Google_Authenticator>`_, `Authy <ht
|
|
|
12
12
|
compatible app. Users can set up auth tokens in their apps easily by using their phone camera to scan `otpauth://
|
|
13
13
|
<https://github.com/google/google-authenticator/wiki/Key-Uri-Format>`_ QR codes provided by PyOTP.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Implementers should read and follow the `HOTP security requirements <https://tools.ietf.org/html/rfc4226#section-7>`_
|
|
16
|
+
and `TOTP security considerations <https://tools.ietf.org/html/rfc6238#section-5>`_ sections of the relevant RFCs. At
|
|
17
|
+
minimum, application implementers should follow this checklist:
|
|
18
|
+
|
|
19
|
+
- Ensure transport confidentiality by using HTTPS
|
|
20
|
+
- Ensure HOTP/TOTP secret confidentiality by storing secrets in a controlled access database
|
|
21
|
+
- Deny replay attacks by rejecting one-time passwords that have been used by the client (this requires storing the most
|
|
22
|
+
recently authenticated timestamp, OTP, or hash of the OTP in your database, and rejecting the OTP when a match is seen)
|
|
23
|
+
- Throttle brute-force attacks against your application's login functionality
|
|
24
|
+
- When implementing a "greenfield" application, consider supporting
|
|
25
|
+
`FIDO U2F <https://en.wikipedia.org/wiki/Universal_2nd_Factor>`_/`WebAuthn <https://www.w3.org/TR/webauthn/>`_ in
|
|
26
|
+
addition to HOTP/TOTP. U2F uses asymmetric cryptography to avoid using a shared secret design, which strengthens your
|
|
27
|
+
MFA solution against server-side attacks. Hardware U2F also sequesters the client secret in a dedicated single-purpose
|
|
28
|
+
device, which strengthens your clients against client-side attacks. And by automating scoping of credentials to
|
|
29
|
+
relying party IDs (application origin/domain names), U2F adds protection against phishing attacks. One implementation of
|
|
30
|
+
FIDO U2F/WebAuthn is PyOTP's sister project, `PyWARP <https://github.com/pyauth/pywarp>`_.
|
|
31
|
+
|
|
32
|
+
We also recommend that implementers read the
|
|
33
|
+
`OWASP Authentication Cheat Sheet <https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md>`_ and
|
|
34
|
+
`NIST SP 800-63-3: Digital Authentication Guideline <https://pages.nist.gov/800-63-3/>`_ for a high level overview of
|
|
35
|
+
authentication best practices.
|
|
16
36
|
|
|
17
37
|
Quick overview of using One Time Passwords on your phone
|
|
18
38
|
--------------------------------------------------------
|
|
@@ -36,25 +56,25 @@ Time-based OTPs
|
|
|
36
56
|
::
|
|
37
57
|
|
|
38
58
|
totp = pyotp.TOTP('base32secret3232')
|
|
39
|
-
totp.now() # => 492039
|
|
59
|
+
totp.now() # => '492039'
|
|
40
60
|
|
|
41
61
|
# OTP verified for current time
|
|
42
|
-
totp.verify(492039) # => True
|
|
62
|
+
totp.verify('492039') # => True
|
|
43
63
|
time.sleep(30)
|
|
44
|
-
totp.verify(492039) # => False
|
|
64
|
+
totp.verify('492039') # => False
|
|
45
65
|
|
|
46
66
|
Counter-based OTPs
|
|
47
67
|
~~~~~~~~~~~~~~~~~~
|
|
48
68
|
::
|
|
49
69
|
|
|
50
70
|
hotp = pyotp.HOTP('base32secret3232')
|
|
51
|
-
hotp.at(0) # => 260182
|
|
52
|
-
hotp.at(1) # =>
|
|
53
|
-
hotp.at(1401) # => 316439
|
|
71
|
+
hotp.at(0) # => '260182'
|
|
72
|
+
hotp.at(1) # => '055283'
|
|
73
|
+
hotp.at(1401) # => '316439'
|
|
54
74
|
|
|
55
75
|
# OTP verified with a counter
|
|
56
|
-
hotp.verify(316439, 1401) # => True
|
|
57
|
-
hotp.verify(316439, 1402) # => False
|
|
76
|
+
hotp.verify('316439', 1401) # => True
|
|
77
|
+
hotp.verify('316439', 1402) # => False
|
|
58
78
|
|
|
59
79
|
Generating a base32 Secret Key
|
|
60
80
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -84,7 +104,7 @@ Working example
|
|
|
84
104
|
|
|
85
105
|
Scan the following barcode with your phone's OTP app (e.g. Google Authenticator):
|
|
86
106
|
|
|
87
|
-
.. image::
|
|
107
|
+
.. image:: https://chart.apis.google.com/chart?cht=qr&chs=250x250&chl=otpauth%3A%2F%2Ftotp%2Falice%40google.com%3Fsecret%3DJBSWY3DPEHPK3PXP
|
|
88
108
|
|
|
89
109
|
Now run the following and compare the output::
|
|
90
110
|
|
|
@@ -103,9 +123,14 @@ Links
|
|
|
103
123
|
* `RFC 6238: TOTP: Time-Based One-Time Password Algorithm <https://tools.ietf.org/html/rfc6238>`_
|
|
104
124
|
* `ROTP <https://github.com/mdp/rotp>`_ - Original Ruby OTP library by `Mark Percival <https://github.com/mdp>`_
|
|
105
125
|
* `OTPHP <https://github.com/lelag/otphp>`_ - PHP port of ROTP by `Le Lag <https://github.com/lelag>`_
|
|
106
|
-
* `OWASP Authentication Cheat Sheet <https://
|
|
126
|
+
* `OWASP Authentication Cheat Sheet <https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md>`_
|
|
107
127
|
* `NIST SP 800-63-3: Digital Authentication Guideline <https://pages.nist.gov/800-63-3/>`_
|
|
108
128
|
|
|
129
|
+
For new applications:
|
|
130
|
+
|
|
131
|
+
* `WebAuthn <https://www.w3.org/TR/webauthn/>`_
|
|
132
|
+
* `PyWARP <https://github.com/pyauth/pywarp>`_
|
|
133
|
+
|
|
109
134
|
.. image:: https://img.shields.io/travis/pyotp/pyotp.svg
|
|
110
135
|
:target: https://travis-ci.org/pyotp/pyotp
|
|
111
136
|
.. image:: https://img.shields.io/codecov/c/github/pyotp/pyotp/master.svg
|
|
@@ -7,9 +7,9 @@ install_requires = [line.rstrip() for line in open(os.path.join(os.path.dirname(
|
|
|
7
7
|
|
|
8
8
|
setup(
|
|
9
9
|
name="pyotp",
|
|
10
|
-
version="2.2.
|
|
10
|
+
version="2.2.8",
|
|
11
11
|
url="https://github.com/pyotp/pyotp",
|
|
12
|
-
license="
|
|
12
|
+
license="MIT License",
|
|
13
13
|
author="PyOTP contributors",
|
|
14
14
|
author_email="kislyuk@gmail.com",
|
|
15
15
|
description="Python One Time Password Library",
|
|
@@ -22,13 +22,15 @@ setup(
|
|
|
22
22
|
test_suite="test",
|
|
23
23
|
classifiers=[
|
|
24
24
|
"Intended Audience :: Developers",
|
|
25
|
-
"License :: OSI Approved ::
|
|
25
|
+
"License :: OSI Approved :: MIT License",
|
|
26
26
|
"Operating System :: MacOS :: MacOS X",
|
|
27
27
|
"Operating System :: POSIX",
|
|
28
28
|
"Programming Language :: Python",
|
|
29
29
|
"Programming Language :: Python :: 2.7",
|
|
30
|
-
"Programming Language :: Python :: 3.3",
|
|
31
30
|
"Programming Language :: Python :: 3.4",
|
|
31
|
+
"Programming Language :: Python :: 3.5",
|
|
32
|
+
"Programming Language :: Python :: 3.6",
|
|
33
|
+
"Programming Language :: Python :: 3.7",
|
|
32
34
|
"Topic :: Software Development :: Libraries :: Python Modules"
|
|
33
35
|
]
|
|
34
36
|
)
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
from __future__ import (absolute_import, division,
|
|
2
2
|
print_function, unicode_literals)
|
|
3
3
|
|
|
4
|
-
import random as _random
|
|
5
|
-
|
|
6
4
|
from pyotp.hotp import HOTP # noqa
|
|
7
5
|
from pyotp.otp import OTP # noqa
|
|
8
6
|
from pyotp.totp import TOTP # noqa
|
|
9
7
|
from . import utils # noqa
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
def random_base32(length=16, random=_random.SystemRandom(),
|
|
9
|
+
def random_base32(length=16, random=None,
|
|
13
10
|
chars=list('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')):
|
|
11
|
+
|
|
12
|
+
# Use secrets module if available (Python version >= 3.6) per PEP 506
|
|
13
|
+
try:
|
|
14
|
+
import secrets
|
|
15
|
+
random = secrets.SystemRandom()
|
|
16
|
+
except ImportError:
|
|
17
|
+
import random as _random
|
|
18
|
+
random = _random.SystemRandom()
|
|
19
|
+
|
|
14
20
|
return ''.join(
|
|
15
21
|
random.choice(chars)
|
|
16
22
|
for _ in range(length)
|
|
@@ -85,12 +85,12 @@ def _compare_digest(s1, s2):
|
|
|
85
85
|
differences |= ord(c1) ^ ord(c2)
|
|
86
86
|
return differences == 0
|
|
87
87
|
|
|
88
|
+
|
|
88
89
|
try:
|
|
89
90
|
# Python 3.3+ and 2.7.7+ include a timing-attack-resistant
|
|
90
91
|
# comparison function, which is probably more reliable than ours.
|
|
91
92
|
# Use it if available.
|
|
92
93
|
from hmac import compare_digest
|
|
93
|
-
|
|
94
94
|
except ImportError:
|
|
95
95
|
compare_digest = _compare_digest
|
|
96
96
|
|
|
@@ -106,4 +106,4 @@ def strings_equal(s1, s2):
|
|
|
106
106
|
"""
|
|
107
107
|
s1 = unicodedata.normalize('NFKC', s1)
|
|
108
108
|
s2 = unicodedata.normalize('NFKC', s2)
|
|
109
|
-
return compare_digest(s1, s2)
|
|
109
|
+
return compare_digest(s1.encode(), s2.encode())
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 1.1
|
|
2
2
|
Name: pyotp
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.8
|
|
4
4
|
Summary: Python One Time Password Library
|
|
5
5
|
Home-page: https://github.com/pyotp/pyotp
|
|
6
6
|
Author: PyOTP contributors
|
|
7
7
|
Author-email: kislyuk@gmail.com
|
|
8
|
-
License:
|
|
8
|
+
License: MIT License
|
|
9
9
|
Description: PyOTP - The Python One-Time Password Library
|
|
10
10
|
============================================
|
|
11
11
|
|
|
@@ -20,7 +20,27 @@ Description: PyOTP - The Python One-Time Password Library
|
|
|
20
20
|
compatible app. Users can set up auth tokens in their apps easily by using their phone camera to scan `otpauth://
|
|
21
21
|
<https://github.com/google/google-authenticator/wiki/Key-Uri-Format>`_ QR codes provided by PyOTP.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Implementers should read and follow the `HOTP security requirements <https://tools.ietf.org/html/rfc4226#section-7>`_
|
|
24
|
+
and `TOTP security considerations <https://tools.ietf.org/html/rfc6238#section-5>`_ sections of the relevant RFCs. At
|
|
25
|
+
minimum, application implementers should follow this checklist:
|
|
26
|
+
|
|
27
|
+
- Ensure transport confidentiality by using HTTPS
|
|
28
|
+
- Ensure HOTP/TOTP secret confidentiality by storing secrets in a controlled access database
|
|
29
|
+
- Deny replay attacks by rejecting one-time passwords that have been used by the client (this requires storing the most
|
|
30
|
+
recently authenticated timestamp, OTP, or hash of the OTP in your database, and rejecting the OTP when a match is seen)
|
|
31
|
+
- Throttle brute-force attacks against your application's login functionality
|
|
32
|
+
- When implementing a "greenfield" application, consider supporting
|
|
33
|
+
`FIDO U2F <https://en.wikipedia.org/wiki/Universal_2nd_Factor>`_/`WebAuthn <https://www.w3.org/TR/webauthn/>`_ in
|
|
34
|
+
addition to HOTP/TOTP. U2F uses asymmetric cryptography to avoid using a shared secret design, which strengthens your
|
|
35
|
+
MFA solution against server-side attacks. Hardware U2F also sequesters the client secret in a dedicated single-purpose
|
|
36
|
+
device, which strengthens your clients against client-side attacks. And by automating scoping of credentials to
|
|
37
|
+
relying party IDs (application origin/domain names), U2F adds protection against phishing attacks. One implementation of
|
|
38
|
+
FIDO U2F/WebAuthn is PyOTP's sister project, `PyWARP <https://github.com/pyauth/pywarp>`_.
|
|
39
|
+
|
|
40
|
+
We also recommend that implementers read the
|
|
41
|
+
`OWASP Authentication Cheat Sheet <https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md>`_ and
|
|
42
|
+
`NIST SP 800-63-3: Digital Authentication Guideline <https://pages.nist.gov/800-63-3/>`_ for a high level overview of
|
|
43
|
+
authentication best practices.
|
|
24
44
|
|
|
25
45
|
Quick overview of using One Time Passwords on your phone
|
|
26
46
|
--------------------------------------------------------
|
|
@@ -44,25 +64,25 @@ Description: PyOTP - The Python One-Time Password Library
|
|
|
44
64
|
::
|
|
45
65
|
|
|
46
66
|
totp = pyotp.TOTP('base32secret3232')
|
|
47
|
-
totp.now() # => 492039
|
|
67
|
+
totp.now() # => '492039'
|
|
48
68
|
|
|
49
69
|
# OTP verified for current time
|
|
50
|
-
totp.verify(492039) # => True
|
|
70
|
+
totp.verify('492039') # => True
|
|
51
71
|
time.sleep(30)
|
|
52
|
-
totp.verify(492039) # => False
|
|
72
|
+
totp.verify('492039') # => False
|
|
53
73
|
|
|
54
74
|
Counter-based OTPs
|
|
55
75
|
~~~~~~~~~~~~~~~~~~
|
|
56
76
|
::
|
|
57
77
|
|
|
58
78
|
hotp = pyotp.HOTP('base32secret3232')
|
|
59
|
-
hotp.at(0) # => 260182
|
|
60
|
-
hotp.at(1) # =>
|
|
61
|
-
hotp.at(1401) # => 316439
|
|
79
|
+
hotp.at(0) # => '260182'
|
|
80
|
+
hotp.at(1) # => '055283'
|
|
81
|
+
hotp.at(1401) # => '316439'
|
|
62
82
|
|
|
63
83
|
# OTP verified with a counter
|
|
64
|
-
hotp.verify(316439, 1401) # => True
|
|
65
|
-
hotp.verify(316439, 1402) # => False
|
|
84
|
+
hotp.verify('316439', 1401) # => True
|
|
85
|
+
hotp.verify('316439', 1402) # => False
|
|
66
86
|
|
|
67
87
|
Generating a base32 Secret Key
|
|
68
88
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -92,7 +112,7 @@ Description: PyOTP - The Python One-Time Password Library
|
|
|
92
112
|
|
|
93
113
|
Scan the following barcode with your phone's OTP app (e.g. Google Authenticator):
|
|
94
114
|
|
|
95
|
-
.. image::
|
|
115
|
+
.. image:: https://chart.apis.google.com/chart?cht=qr&chs=250x250&chl=otpauth%3A%2F%2Ftotp%2Falice%40google.com%3Fsecret%3DJBSWY3DPEHPK3PXP
|
|
96
116
|
|
|
97
117
|
Now run the following and compare the output::
|
|
98
118
|
|
|
@@ -111,9 +131,14 @@ Description: PyOTP - The Python One-Time Password Library
|
|
|
111
131
|
* `RFC 6238: TOTP: Time-Based One-Time Password Algorithm <https://tools.ietf.org/html/rfc6238>`_
|
|
112
132
|
* `ROTP <https://github.com/mdp/rotp>`_ - Original Ruby OTP library by `Mark Percival <https://github.com/mdp>`_
|
|
113
133
|
* `OTPHP <https://github.com/lelag/otphp>`_ - PHP port of ROTP by `Le Lag <https://github.com/lelag>`_
|
|
114
|
-
* `OWASP Authentication Cheat Sheet <https://
|
|
134
|
+
* `OWASP Authentication Cheat Sheet <https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md>`_
|
|
115
135
|
* `NIST SP 800-63-3: Digital Authentication Guideline <https://pages.nist.gov/800-63-3/>`_
|
|
116
136
|
|
|
137
|
+
For new applications:
|
|
138
|
+
|
|
139
|
+
* `WebAuthn <https://www.w3.org/TR/webauthn/>`_
|
|
140
|
+
* `PyWARP <https://github.com/pyauth/pywarp>`_
|
|
141
|
+
|
|
117
142
|
.. image:: https://img.shields.io/travis/pyotp/pyotp.svg
|
|
118
143
|
:target: https://travis-ci.org/pyotp/pyotp
|
|
119
144
|
.. image:: https://img.shields.io/codecov/c/github/pyotp/pyotp/master.svg
|
|
@@ -128,11 +153,13 @@ Description: PyOTP - The Python One-Time Password Library
|
|
|
128
153
|
Platform: MacOS X
|
|
129
154
|
Platform: Posix
|
|
130
155
|
Classifier: Intended Audience :: Developers
|
|
131
|
-
Classifier: License :: OSI Approved ::
|
|
156
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
132
157
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
133
158
|
Classifier: Operating System :: POSIX
|
|
134
159
|
Classifier: Programming Language :: Python
|
|
135
160
|
Classifier: Programming Language :: Python :: 2.7
|
|
136
|
-
Classifier: Programming Language :: Python :: 3.3
|
|
137
161
|
Classifier: Programming Language :: Python :: 3.4
|
|
162
|
+
Classifier: Programming Language :: Python :: 3.5
|
|
163
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
164
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
138
165
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
@@ -261,6 +261,9 @@ class StringComparisonTest(CompareDigestTest):
|
|
|
261
261
|
def test_fullwidth_input(self):
|
|
262
262
|
self.assertTrue(self.method("xs12345", "xs12345"))
|
|
263
263
|
|
|
264
|
+
def test_unicode_equal(self):
|
|
265
|
+
self.assertTrue(self.method("ěšč45", "ěšč45"))
|
|
266
|
+
|
|
264
267
|
|
|
265
268
|
class CounterOffsetTest(unittest.TestCase):
|
|
266
269
|
def test_counter_offset(self):
|
|
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
|