aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cryptography/hazmat/oath/hotp.py7
-rw-r--r--docs/hazmat/oath/hotp.rst9
-rw-r--r--pytest.ini1
-rw-r--r--tests/hazmat/oath/test_hotp.py4
4 files changed, 12 insertions, 9 deletions
diff --git a/cryptography/hazmat/oath/hotp.py b/cryptography/hazmat/oath/hotp.py
index 319e66f2..a04d0d49 100644
--- a/cryptography/hazmat/oath/hotp.py
+++ b/cryptography/hazmat/oath/hotp.py
@@ -12,6 +12,7 @@
# limitations under the License.
import struct
+import six
from cryptography.hazmat.primitives import constant_time
from cryptography.hazmat.primitives.hashes import SHA1
@@ -25,7 +26,8 @@ class HOTP(object):
def generate(self, counter):
sbit = self._dynamic_truncate(counter)
- return str(sbit % (10**self.length)).zfill(self.length)
+ foo = sbit % (10**self.length)
+ return ('%s' % foo).zfill(self.length).encode()
def verify(self, hotp, counter):
return constant_time.bytes_eq(self.generate(counter), hotp)
@@ -35,7 +37,8 @@ class HOTP(object):
ctx.update(struct.pack(">Q", counter))
hmac_value = ctx.finalize()
- offset_bits = ord(hmac_value[19]) & 0b1111
+ offset_bits = six.indexbytes(hmac_value, 19) & 0b1111
+
offset = int(offset_bits)
P = hmac_value[offset:offset+4]
return struct.unpack(">I", P)[0] & 0x7fffffff
diff --git a/docs/hazmat/oath/hotp.rst b/docs/hazmat/oath/hotp.rst
index d84f5bdf..614933f9 100644
--- a/docs/hazmat/oath/hotp.rst
+++ b/docs/hazmat/oath/hotp.rst
@@ -17,7 +17,7 @@ values based on Hash-based message authentication codes (HMAC).
This is an implementation of :rfc:`4226`.
- .. doctest::
+ .. code-block:: python
>>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.oath.hotp import HOTP
@@ -35,12 +35,11 @@ values based on Hash-based message authentication codes (HMAC).
.. method:: generate(counter)
- :param counter: The counter value used to generate the one time password.
+ :param int counter: The counter value used to generate the one time password.
:return: A one time password value.
.. method:: verify(hotp, counter)
- :param hotp: The one time password value to validate.
- :param counter: The counter value to validate against.
+ :param bytes hotp: The one time password value to validate.
+ :param bytes counter: The counter value to validate against.
:return: ``True`` if the one time password value is valid. ``False`` if otherwise.
-
diff --git a/pytest.ini b/pytest.ini
index 3f65e30e..77360d16 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -7,3 +7,4 @@ markers =
pbkdf2hmac: this test requires a backend providing PBKDF2HMACBackend
rsa: this test requires a backend providing RSABackend
supported: parametrized test requiring only_if and skip_message
+ oath: this test requires a backend providing HMACBackend
diff --git a/tests/hazmat/oath/test_hotp.py b/tests/hazmat/oath/test_hotp.py
index d2d3c941..cd06c79f 100644
--- a/tests/hazmat/oath/test_hotp.py
+++ b/tests/hazmat/oath/test_hotp.py
@@ -26,11 +26,11 @@ class TestHOTP(object):
def test_truncate(self, backend, params):
secret = params["secret"]
counter = int(params["counter"])
- truncated_value = params["truncated"]
+ truncated = params["truncated"]
hotp = HOTP(secret, 6, backend)
- assert hex(hotp._dynamic_truncate(counter))[2:] == truncated_value
+ assert hex(hotp._dynamic_truncate(counter))[2:] == truncated.decode()
@pytest.mark.parametrize("params", vectors)
def test_generate(self, backend, params):