PyOTP 2.4.0__tar.gz → 2.4.1__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.4.0/src/pyotp.egg-info → pyotp-2.4.1}/PKG-INFO +1 -1
- {pyotp-2.4.0 → pyotp-2.4.1}/setup.py +1 -1
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp/__init__.py +2 -2
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp/hotp.py +1 -1
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp/totp.py +11 -2
- {pyotp-2.4.0 → pyotp-2.4.1/src/pyotp.egg-info}/PKG-INFO +1 -1
- {pyotp-2.4.0 → pyotp-2.4.1}/test.py +37 -3
- {pyotp-2.4.0 → pyotp-2.4.1}/LICENSE +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/MANIFEST.in +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/README.rst +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/requirements.txt +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/setup.cfg +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp/compat.py +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp/otp.py +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp/py.typed +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp/utils.py +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp.egg-info/SOURCES.txt +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp.egg-info/dependency_links.txt +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp.egg-info/not-zip-safe +0 -0
- {pyotp-2.4.0 → pyotp-2.4.1}/src/pyotp.egg-info/top_level.txt +0 -0
|
@@ -84,9 +84,9 @@ def parse_uri(uri: str) -> OTP:
|
|
|
84
84
|
raise ValueError('Digits may only be 6 or 8')
|
|
85
85
|
otp_data['digits'] = digits
|
|
86
86
|
elif key == 'period':
|
|
87
|
-
otp_data['interval'] = value
|
|
87
|
+
otp_data['interval'] = int(value)
|
|
88
88
|
elif key == 'counter':
|
|
89
|
-
otp_data['initial_count'] = value
|
|
89
|
+
otp_data['initial_count'] = int(value)
|
|
90
90
|
else:
|
|
91
91
|
raise ValueError('{} is not a valid parameter'.format(key))
|
|
92
92
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from typing import Any, Union, Optional
|
|
2
2
|
|
|
3
|
+
import calendar
|
|
3
4
|
import datetime
|
|
4
5
|
import time
|
|
5
6
|
|
|
@@ -80,5 +81,13 @@ class TOTP(OTP):
|
|
|
80
81
|
digits=self.digits, period=self.interval)
|
|
81
82
|
|
|
82
83
|
def timecode(self, for_time: datetime.datetime) -> int:
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
"""
|
|
85
|
+
Accepts either a timezone naive (`for_time.tzinfo is None`) or
|
|
86
|
+
a timezone aware datetime as argument and returns the
|
|
87
|
+
corresponding counter value (timecode).
|
|
88
|
+
|
|
89
|
+
"""
|
|
90
|
+
if for_time.tzinfo:
|
|
91
|
+
return int(calendar.timegm(for_time.utctimetuple()) / self.interval)
|
|
92
|
+
else:
|
|
93
|
+
return int(time.mktime(for_time.timetuple()) / self.interval)
|
|
@@ -339,6 +339,7 @@ class ValidWindowTest(unittest.TestCase):
|
|
|
339
339
|
self.assertTrue(totp.verify("681610", 200, 1))
|
|
340
340
|
self.assertFalse(totp.verify("195979", 200, 1))
|
|
341
341
|
|
|
342
|
+
|
|
342
343
|
class ParseUriTest(unittest.TestCase):
|
|
343
344
|
def test_invalids(self):
|
|
344
345
|
with self.assertRaises(ValueError) as cm:
|
|
@@ -369,15 +370,48 @@ class ParseUriTest(unittest.TestCase):
|
|
|
369
370
|
pyotp.parse_uri('otpauth://totp?algorithm=aes')
|
|
370
371
|
self.assertEqual('Invalid value for algorithm, must be SHA1, SHA256 or SHA512', str(cm.exception))
|
|
371
372
|
|
|
373
|
+
@unittest.skipIf(sys.version_info < (3, 6), "Skipping test that requires deterministic dict key enumeration")
|
|
372
374
|
def test_algorithms(self):
|
|
373
|
-
otp = pyotp.parse_uri('otpauth://totp?algorithm=SHA1&secret=
|
|
375
|
+
otp = pyotp.parse_uri('otpauth://totp?algorithm=SHA1&secret=GEZDGNBV&algorithm=SHA1')
|
|
376
|
+
self.assertEqual(hashlib.sha1, otp.digest)
|
|
377
|
+
self.assertEqual(otp.at(0), '734055')
|
|
378
|
+
self.assertEqual(otp.at(30), '662488')
|
|
379
|
+
self.assertEqual(otp.at(60), '289363')
|
|
380
|
+
self.assertEqual(otp.provisioning_uri(), 'otpauth://totp/Secret?secret=GEZDGNBV')
|
|
381
|
+
self.assertEqual(otp.provisioning_uri(name='n', issuer_name='i'), 'otpauth://totp/i:n?secret=GEZDGNBV&issuer=i')
|
|
382
|
+
|
|
383
|
+
otp = pyotp.parse_uri('otpauth://totp?algorithm=SHA1&secret=GEZDGNBV&algorithm=SHA1&period=60')
|
|
384
|
+
self.assertEqual(hashlib.sha1, otp.digest)
|
|
385
|
+
self.assertEqual(otp.at(30), '734055')
|
|
386
|
+
self.assertEqual(otp.at(60), '662488')
|
|
387
|
+
self.assertEqual(otp.provisioning_uri(name='n', issuer_name='i'),
|
|
388
|
+
'otpauth://totp/i:n?secret=GEZDGNBV&issuer=i&period=60')
|
|
389
|
+
|
|
390
|
+
otp = pyotp.parse_uri('otpauth://hotp?algorithm=SHA1&secret=GEZDGNBV&algorithm=SHA1')
|
|
391
|
+
self.assertEqual(hashlib.sha1, otp.digest)
|
|
392
|
+
self.assertEqual(otp.at(0), '734055')
|
|
393
|
+
self.assertEqual(otp.at(1), '662488')
|
|
394
|
+
self.assertEqual(otp.at(2), '289363')
|
|
395
|
+
self.assertEqual(otp.provisioning_uri(name='n', issuer_name='i'),
|
|
396
|
+
'otpauth://hotp/i:n?secret=GEZDGNBV&issuer=i&counter=0')
|
|
397
|
+
|
|
398
|
+
otp = pyotp.parse_uri('otpauth://hotp?algorithm=SHA1&secret=GEZDGNBV&algorithm=SHA1&counter=1')
|
|
374
399
|
self.assertEqual(hashlib.sha1, otp.digest)
|
|
400
|
+
self.assertEqual(otp.at(0), '662488')
|
|
401
|
+
self.assertEqual(otp.at(1), '289363')
|
|
402
|
+
self.assertEqual(otp.provisioning_uri(name='n', issuer_name='i'),
|
|
403
|
+
'otpauth://hotp/i:n?secret=GEZDGNBV&issuer=i&counter=1')
|
|
375
404
|
|
|
376
|
-
otp = pyotp.parse_uri('otpauth://totp?algorithm=SHA1&secret=
|
|
405
|
+
otp = pyotp.parse_uri('otpauth://totp?algorithm=SHA1&secret=GEZDGNBV&algorithm=SHA256')
|
|
377
406
|
self.assertEqual(hashlib.sha256, otp.digest)
|
|
407
|
+
self.assertEqual(otp.at(0), '918961')
|
|
408
|
+
self.assertEqual(otp.at(9000), '934470')
|
|
378
409
|
|
|
379
|
-
otp = pyotp.parse_uri('otpauth://totp?algorithm=SHA1&secret=
|
|
410
|
+
otp = pyotp.parse_uri('otpauth://totp?algorithm=SHA1&secret=GEZDGNBV&algorithm=SHA512')
|
|
380
411
|
self.assertEqual(hashlib.sha512, otp.digest)
|
|
412
|
+
self.assertEqual(otp.at(0), '816660')
|
|
413
|
+
self.assertEqual(otp.at(9000), '524153')
|
|
414
|
+
|
|
381
415
|
|
|
382
416
|
class Timecop(object):
|
|
383
417
|
"""
|
|
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
|