From 18ca44bfef0fe2908d9da3b3008941325d04a971 Mon Sep 17 00:00:00 2001 From: Ayrx Date: Wed, 12 Feb 2014 18:38:28 +0800 Subject: Added documentation for HOTP implementation. --- docs/hazmat/oath/hotp.rst | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 docs/hazmat/oath/hotp.rst (limited to 'docs/hazmat') diff --git a/docs/hazmat/oath/hotp.rst b/docs/hazmat/oath/hotp.rst new file mode 100644 index 00000000..d84f5bdf --- /dev/null +++ b/docs/hazmat/oath/hotp.rst @@ -0,0 +1,46 @@ +.. hazmat:: + +HMAC-Based One-Time Password Algorithm +====================================== + +.. currentmodule:: cryptography.hazmat.oath.hotp + +This module contains functions for generating and verifying one time password +values based on Hash-based message authentication codes (HMAC). + +.. class:: HOTP(secret, length, backend) + + HOTP objects take a ``secret`` and ``length`` parameter. The ``secret`` + should be randomly generated bytes and is recommended to be 160 bits in + length. The ``length`` parameter controls the length of the generated + one time password and is recommended to be at least a 6 digit value. + + This is an implementation of :rfc:`4226`. + + .. doctest:: + + >>> from cryptography.hazmat.backends import default_backend + >>> from cryptography.hazmat.oath.hotp import HOTP + >>> hotp = HOTP(secret, 6, backend=default_backend) + >>> hotp.generate(0) + 958695 + >>> hotp.verify("958695", 0) + True + + :param secret: Secret key as ``bytes``. + :param length: Length of generated one time password as ``int``. + :param backend: A + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` + provider. + + .. method:: generate(counter) + + :param 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. + :return: ``True`` if the one time password value is valid. ``False`` if otherwise. + -- cgit v1.2.3 From b2ee044298caf5772fb8774dc691add3afe8cdc1 Mon Sep 17 00:00:00 2001 From: Ayrx Date: Wed, 12 Feb 2014 22:22:01 +0800 Subject: Minor changes for python3 compat and documentation changes --- docs/hazmat/oath/hotp.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'docs/hazmat') 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. - -- cgit v1.2.3 From a7769110ef8f575105847f84cadf6bb5b9aa5fba Mon Sep 17 00:00:00 2001 From: Ayrx Date: Thu, 13 Feb 2014 12:27:56 +0800 Subject: Updated according to code review feedback. --- docs/hazmat/oath/hotp.rst | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'docs/hazmat') diff --git a/docs/hazmat/oath/hotp.rst b/docs/hazmat/oath/hotp.rst index 614933f9..1dee26b0 100644 --- a/docs/hazmat/oath/hotp.rst +++ b/docs/hazmat/oath/hotp.rst @@ -17,18 +17,20 @@ values based on Hash-based message authentication codes (HMAC). This is an implementation of :rfc:`4226`. - .. code-block:: python + .. doctest:: + >>> import os >>> from cryptography.hazmat.backends import default_backend >>> from cryptography.hazmat.oath.hotp import HOTP - >>> hotp = HOTP(secret, 6, backend=default_backend) + + >>> key = "12345678901234567890" + >>> hotp = HOTP(key, 6, backend=default_backend()) >>> hotp.generate(0) - 958695 - >>> hotp.verify("958695", 0) - True + '755224' + >>> hotp.verify("755224", 0) - :param secret: Secret key as ``bytes``. - :param length: Length of generated one time password as ``int``. + :param bytes secret: Secret key as ``bytes``. + :param int length: Length of generated one time password as ``int``. :param backend: A :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` provider. @@ -36,7 +38,7 @@ values based on Hash-based message authentication codes (HMAC). .. method:: generate(counter) :param int counter: The counter value used to generate the one time password. - :return: A one time password value. + :return bytes: A one time password value. .. method:: verify(hotp, counter) -- cgit v1.2.3 From 25b1d21b40f531450877bcfbee55406b28111dca Mon Sep 17 00:00:00 2001 From: Ayrx Date: Thu, 13 Feb 2014 15:30:20 +0800 Subject: Updated documentation. --- docs/hazmat/oath/hotp.rst | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'docs/hazmat') diff --git a/docs/hazmat/oath/hotp.rst b/docs/hazmat/oath/hotp.rst index 1dee26b0..7aff330f 100644 --- a/docs/hazmat/oath/hotp.rst +++ b/docs/hazmat/oath/hotp.rst @@ -8,12 +8,12 @@ HMAC-Based One-Time Password Algorithm This module contains functions for generating and verifying one time password values based on Hash-based message authentication codes (HMAC). -.. class:: HOTP(secret, length, backend) +.. class:: HOTP(key, length, backend) - HOTP objects take a ``secret`` and ``length`` parameter. The ``secret`` + HOTP objects take a ``key`` and ``length`` parameter. The ``key`` should be randomly generated bytes and is recommended to be 160 bits in length. The ``length`` parameter controls the length of the generated - one time password and is recommended to be at least a 6 digit value. + one time password and must be >= 6. This is an implementation of :rfc:`4226`. @@ -23,17 +23,22 @@ values based on Hash-based message authentication codes (HMAC). >>> from cryptography.hazmat.backends import default_backend >>> from cryptography.hazmat.oath.hotp import HOTP - >>> key = "12345678901234567890" + >>> key = b"12345678901234567890" >>> hotp = HOTP(key, 6, backend=default_backend()) >>> hotp.generate(0) '755224' - >>> hotp.verify("755224", 0) + >>> hotp.verify(b"755224", 0) - :param bytes secret: Secret key as ``bytes``. + :param bytes key: Secret key as ``bytes``. This value must be generated in a + cryptographically secure fashion and be at least 128 bits. + It is recommended that the key be 160 bits. :param int length: Length of generated one time password as ``int``. :param backend: A :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` provider. + :raises ValueError: This is raised if the provided ``key`` or ``length`` + parameters are shorter than required. + .. method:: generate(counter) @@ -44,4 +49,5 @@ values based on Hash-based message authentication codes (HMAC). :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. + :raises cryptography.exceptions.InvalidToken: This is raised when the supplied HOTP + does not match the expected HOTP. -- cgit v1.2.3 From b5189afaf1dd1c06edd0efe3d6791ea7c40e31c7 Mon Sep 17 00:00:00 2001 From: Ayrx Date: Thu, 13 Feb 2014 18:52:31 +0800 Subject: Added a max limit of 8 on length parameter. Updated documentation. --- docs/hazmat/oath.rst | 59 +++++++++++++++++++++++++++++++++++++++++++++++ docs/hazmat/oath/hotp.rst | 53 ------------------------------------------ 2 files changed, 59 insertions(+), 53 deletions(-) create mode 100644 docs/hazmat/oath.rst delete mode 100644 docs/hazmat/oath/hotp.rst (limited to 'docs/hazmat') diff --git a/docs/hazmat/oath.rst b/docs/hazmat/oath.rst new file mode 100644 index 00000000..b936f0e5 --- /dev/null +++ b/docs/hazmat/oath.rst @@ -0,0 +1,59 @@ +.. hazmat:: + +OATH +==== + +.. currentmodule:: cryptography.hazmat.oath + +This module contains algorithms under the umbrella of the +Initiative for Open Authentication (OATH). + +Currently, it contains an algorithm for generating and verifying +one time password values based on Hash-based message authentication +codes (HMAC). + +.. currentmodule:: cryptography.hazmat.oath.hotp + +.. class:: HOTP(key, length, backend) + + HOTP objects take a ``key`` and ``length`` parameter. The ``key`` + should be randomly generated bytes and is recommended to be 160 bits in + length. The ``length`` parameter controls the length of the generated + one time password and must be >= 6 and <= 8. + + This is an implementation of :rfc:`4226`. + + .. doctest:: + + >>> import os + >>> from cryptography.hazmat.backends import default_backend + >>> from cryptography.hazmat.oath.hotp import HOTP + + >>> key = b"12345678901234567890" + >>> hotp = HOTP(key, 6, backend=default_backend()) + >>> hotp.generate(0) + '755224' + >>> hotp.verify(b"755224", 0) + + :param bytes key: Secret key as ``bytes``. This value must be generated in a + cryptographically secure fashion and be at least 128 bits. + It is recommended that the key be 160 bits. + :param int length: Length of generated one time password as ``int``. + :param backend: A + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` + provider. + :raises ValueError: This is raised if the provided ``key`` is shorter 128 bits + or if the ``length`` parameter is not between 6 to 8. + + + .. method:: generate(counter) + + :param int counter: The counter value used to generate the one time password. + :return bytes: A one time password value. + + .. method:: verify(hotp, counter) + + :param bytes hotp: The one time password value to validate. + :param bytes counter: The counter value to validate against. + :raises cryptography.exceptions.InvalidToken: This is raised when the supplied HOTP + does not match the expected HOTP. diff --git a/docs/hazmat/oath/hotp.rst b/docs/hazmat/oath/hotp.rst deleted file mode 100644 index 7aff330f..00000000 --- a/docs/hazmat/oath/hotp.rst +++ /dev/null @@ -1,53 +0,0 @@ -.. hazmat:: - -HMAC-Based One-Time Password Algorithm -====================================== - -.. currentmodule:: cryptography.hazmat.oath.hotp - -This module contains functions for generating and verifying one time password -values based on Hash-based message authentication codes (HMAC). - -.. class:: HOTP(key, length, backend) - - HOTP objects take a ``key`` and ``length`` parameter. The ``key`` - should be randomly generated bytes and is recommended to be 160 bits in - length. The ``length`` parameter controls the length of the generated - one time password and must be >= 6. - - This is an implementation of :rfc:`4226`. - - .. doctest:: - - >>> import os - >>> from cryptography.hazmat.backends import default_backend - >>> from cryptography.hazmat.oath.hotp import HOTP - - >>> key = b"12345678901234567890" - >>> hotp = HOTP(key, 6, backend=default_backend()) - >>> hotp.generate(0) - '755224' - >>> hotp.verify(b"755224", 0) - - :param bytes key: Secret key as ``bytes``. This value must be generated in a - cryptographically secure fashion and be at least 128 bits. - It is recommended that the key be 160 bits. - :param int length: Length of generated one time password as ``int``. - :param backend: A - :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` - provider. - :raises ValueError: This is raised if the provided ``key`` or ``length`` - parameters are shorter than required. - - - .. method:: generate(counter) - - :param int counter: The counter value used to generate the one time password. - :return bytes: A one time password value. - - .. method:: verify(hotp, counter) - - :param bytes hotp: The one time password value to validate. - :param bytes counter: The counter value to validate against. - :raises cryptography.exceptions.InvalidToken: This is raised when the supplied HOTP - does not match the expected HOTP. -- cgit v1.2.3 From ebadb6b293748786c45fb34685b25000be4df2e7 Mon Sep 17 00:00:00 2001 From: Ayrx Date: Sat, 15 Feb 2014 20:32:07 +0800 Subject: Updated docs with notes on throttling and resynchronization. --- docs/hazmat/oath.rst | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'docs/hazmat') diff --git a/docs/hazmat/oath.rst b/docs/hazmat/oath.rst index b936f0e5..91c23566 100644 --- a/docs/hazmat/oath.rst +++ b/docs/hazmat/oath.rst @@ -57,3 +57,39 @@ codes (HMAC). :param bytes counter: The counter value to validate against. :raises cryptography.exceptions.InvalidToken: This is raised when the supplied HOTP does not match the expected HOTP. + +Throttling +---------- + +Due to the fact that the HOTP algorithm generates rather short tokens that are 6 - 8 digits +long, brute force attacks are possible. It is highly recommended that the server that +validates the token implement a throttling scheme that locks out the account for a period of +time after a number of failed attempts. The number of allowed attempts should be as low as +possible while still ensuring that usability is not significantly impacted. + +Re-synchronization of the Counter +--------------------------------- + +The server's counter value should only be incremented on a successful HOTP authentication. +However, the counter on the client is incremented every time a new HOTP value is requested. +This can lead to the counter value being out of synchronization between the client and server. + +Due to this, it is highly recommended that the server sets a look-ahead window that allows the +server to calculate the next ``x`` HOTP values and check them against the supplied HOTP value. +This can be accomplished with something similar to the following code. + +.. code-block:: python + + def verify(hotp, counter, look_ahead): + assert look_ahead >= 0 + correct_counter = None + + otp = HOTP(key, 6, default_backend()) + for count in range(counter, counter+look_ahead): + try: + otp.verify(hotp, count) + correct_counter = count + except InvalidToken: + pass + + return correct_counter \ No newline at end of file -- cgit v1.2.3 From 26d276f2a9f7b1ca155cb7cced139b2d15baf272 Mon Sep 17 00:00:00 2001 From: Ayrx Date: Mon, 17 Feb 2014 12:40:30 +0800 Subject: Updated documentation. --- docs/hazmat/oath.rst | 95 ---------------------------------------- docs/hazmat/primitives/index.rst | 1 + docs/hazmat/primitives/otp.rst | 95 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 95 deletions(-) delete mode 100644 docs/hazmat/oath.rst create mode 100644 docs/hazmat/primitives/otp.rst (limited to 'docs/hazmat') diff --git a/docs/hazmat/oath.rst b/docs/hazmat/oath.rst deleted file mode 100644 index 91c23566..00000000 --- a/docs/hazmat/oath.rst +++ /dev/null @@ -1,95 +0,0 @@ -.. hazmat:: - -OATH -==== - -.. currentmodule:: cryptography.hazmat.oath - -This module contains algorithms under the umbrella of the -Initiative for Open Authentication (OATH). - -Currently, it contains an algorithm for generating and verifying -one time password values based on Hash-based message authentication -codes (HMAC). - -.. currentmodule:: cryptography.hazmat.oath.hotp - -.. class:: HOTP(key, length, backend) - - HOTP objects take a ``key`` and ``length`` parameter. The ``key`` - should be randomly generated bytes and is recommended to be 160 bits in - length. The ``length`` parameter controls the length of the generated - one time password and must be >= 6 and <= 8. - - This is an implementation of :rfc:`4226`. - - .. doctest:: - - >>> import os - >>> from cryptography.hazmat.backends import default_backend - >>> from cryptography.hazmat.oath.hotp import HOTP - - >>> key = b"12345678901234567890" - >>> hotp = HOTP(key, 6, backend=default_backend()) - >>> hotp.generate(0) - '755224' - >>> hotp.verify(b"755224", 0) - - :param bytes key: Secret key as ``bytes``. This value must be generated in a - cryptographically secure fashion and be at least 128 bits. - It is recommended that the key be 160 bits. - :param int length: Length of generated one time password as ``int``. - :param backend: A - :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` - provider. - :raises ValueError: This is raised if the provided ``key`` is shorter 128 bits - or if the ``length`` parameter is not between 6 to 8. - - - .. method:: generate(counter) - - :param int counter: The counter value used to generate the one time password. - :return bytes: A one time password value. - - .. method:: verify(hotp, counter) - - :param bytes hotp: The one time password value to validate. - :param bytes counter: The counter value to validate against. - :raises cryptography.exceptions.InvalidToken: This is raised when the supplied HOTP - does not match the expected HOTP. - -Throttling ----------- - -Due to the fact that the HOTP algorithm generates rather short tokens that are 6 - 8 digits -long, brute force attacks are possible. It is highly recommended that the server that -validates the token implement a throttling scheme that locks out the account for a period of -time after a number of failed attempts. The number of allowed attempts should be as low as -possible while still ensuring that usability is not significantly impacted. - -Re-synchronization of the Counter ---------------------------------- - -The server's counter value should only be incremented on a successful HOTP authentication. -However, the counter on the client is incremented every time a new HOTP value is requested. -This can lead to the counter value being out of synchronization between the client and server. - -Due to this, it is highly recommended that the server sets a look-ahead window that allows the -server to calculate the next ``x`` HOTP values and check them against the supplied HOTP value. -This can be accomplished with something similar to the following code. - -.. code-block:: python - - def verify(hotp, counter, look_ahead): - assert look_ahead >= 0 - correct_counter = None - - otp = HOTP(key, 6, default_backend()) - for count in range(counter, counter+look_ahead): - try: - otp.verify(hotp, count) - correct_counter = count - except InvalidToken: - pass - - return correct_counter \ No newline at end of file diff --git a/docs/hazmat/primitives/index.rst b/docs/hazmat/primitives/index.rst index 38ed24c9..9121d156 100644 --- a/docs/hazmat/primitives/index.rst +++ b/docs/hazmat/primitives/index.rst @@ -14,3 +14,4 @@ Primitives rsa constant-time interfaces + otp diff --git a/docs/hazmat/primitives/otp.rst b/docs/hazmat/primitives/otp.rst new file mode 100644 index 00000000..ad2c856a --- /dev/null +++ b/docs/hazmat/primitives/otp.rst @@ -0,0 +1,95 @@ +.. hazmat:: + +One Time Password +================= + +.. currentmodule:: cryptography.hazmat.primitives.otp + +This module contains algorithms for generating and verifying one +time passwords. + +Currently, it contains an algorithm for generating and verifying +one time password values based on Hash-based message authentication +codes (HMAC). + +.. currentmodule:: cryptography.hazmat.primitives.otp.hotp + +.. class:: HOTP(key, length, backend) + + HOTP objects take a ``key`` and ``length`` parameter. The ``key`` + should be randomly generated bytes and is recommended to be 160 bits in + length. The ``length`` parameter controls the length of the generated + one time password and must be >= 6 and <= 8. + + This is an implementation of :rfc:`4226`. + + .. doctest:: + + >>> import os + >>> from cryptography.hazmat.backends import default_backend + >>> from cryptography.hazmat.primitives.otp.hotp import HOTP + + >>> key = b"12345678901234567890" + >>> hotp = HOTP(key, 6, backend=default_backend()) + >>> hotp.generate(0) + '755224' + >>> hotp.verify(b"755224", 0) + + :param bytes key: Secret key as ``bytes``. This value must be generated in a + cryptographically secure fashion and be at least 128 bits. + It is recommended that the key be 160 bits. + :param int length: Length of generated one time password as ``int``. + :param backend: A + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` + provider. + :raises ValueError: This is raised if the provided ``key`` is shorter 128 bits + or if the ``length`` parameter is not between 6 to 8. + + + .. method:: generate(counter) + + :param int counter: The counter value used to generate the one time password. + :return bytes: A one time password value. + + .. method:: verify(hotp, counter) + + :param bytes hotp: The one time password value to validate. + :param bytes counter: The counter value to validate against. + :raises cryptography.exceptions.InvalidToken: This is raised when the supplied HOTP + does not match the expected HOTP. + +Throttling +---------- + +Due to the fact that the HOTP algorithm generates rather short tokens that are 6 - 8 digits +long, brute force attacks are possible. It is highly recommended that the server that +validates the token implement a throttling scheme that locks out the account for a period of +time after a number of failed attempts. The number of allowed attempts should be as low as +possible while still ensuring that usability is not significantly impacted. + +Re-synchronization of the Counter +--------------------------------- + +The server's counter value should only be incremented on a successful HOTP authentication. +However, the counter on the client is incremented every time a new HOTP value is requested. +This can lead to the counter value being out of synchronization between the client and server. + +Due to this, it is highly recommended that the server sets a look-ahead window that allows the +server to calculate the next ``x`` HOTP values and check them against the supplied HOTP value. +This can be accomplished with something similar to the following code. + +.. code-block:: python + + def verify(hotp, counter, look_ahead): + assert look_ahead >= 0 + correct_counter = None + + otp = HOTP(key, 6, default_backend()) + for count in range(counter, counter+look_ahead): + try: + otp.verify(hotp, count) + correct_counter = count + except InvalidToken: + pass + + return correct_counter \ No newline at end of file -- cgit v1.2.3 From 8c1ad596b02f89cde6040e8626e07ca352182130 Mon Sep 17 00:00:00 2001 From: Ayrx Date: Tue, 18 Feb 2014 12:33:55 +0800 Subject: Changed module name from otp to twofactor. --- docs/hazmat/primitives/index.rst | 2 +- docs/hazmat/primitives/otp.rst | 95 ------------------------------------ docs/hazmat/primitives/twofactor.rst | 94 +++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 96 deletions(-) delete mode 100644 docs/hazmat/primitives/otp.rst create mode 100644 docs/hazmat/primitives/twofactor.rst (limited to 'docs/hazmat') diff --git a/docs/hazmat/primitives/index.rst b/docs/hazmat/primitives/index.rst index 9121d156..5199d493 100644 --- a/docs/hazmat/primitives/index.rst +++ b/docs/hazmat/primitives/index.rst @@ -14,4 +14,4 @@ Primitives rsa constant-time interfaces - otp + twofactor diff --git a/docs/hazmat/primitives/otp.rst b/docs/hazmat/primitives/otp.rst deleted file mode 100644 index ad2c856a..00000000 --- a/docs/hazmat/primitives/otp.rst +++ /dev/null @@ -1,95 +0,0 @@ -.. hazmat:: - -One Time Password -================= - -.. currentmodule:: cryptography.hazmat.primitives.otp - -This module contains algorithms for generating and verifying one -time passwords. - -Currently, it contains an algorithm for generating and verifying -one time password values based on Hash-based message authentication -codes (HMAC). - -.. currentmodule:: cryptography.hazmat.primitives.otp.hotp - -.. class:: HOTP(key, length, backend) - - HOTP objects take a ``key`` and ``length`` parameter. The ``key`` - should be randomly generated bytes and is recommended to be 160 bits in - length. The ``length`` parameter controls the length of the generated - one time password and must be >= 6 and <= 8. - - This is an implementation of :rfc:`4226`. - - .. doctest:: - - >>> import os - >>> from cryptography.hazmat.backends import default_backend - >>> from cryptography.hazmat.primitives.otp.hotp import HOTP - - >>> key = b"12345678901234567890" - >>> hotp = HOTP(key, 6, backend=default_backend()) - >>> hotp.generate(0) - '755224' - >>> hotp.verify(b"755224", 0) - - :param bytes key: Secret key as ``bytes``. This value must be generated in a - cryptographically secure fashion and be at least 128 bits. - It is recommended that the key be 160 bits. - :param int length: Length of generated one time password as ``int``. - :param backend: A - :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` - provider. - :raises ValueError: This is raised if the provided ``key`` is shorter 128 bits - or if the ``length`` parameter is not between 6 to 8. - - - .. method:: generate(counter) - - :param int counter: The counter value used to generate the one time password. - :return bytes: A one time password value. - - .. method:: verify(hotp, counter) - - :param bytes hotp: The one time password value to validate. - :param bytes counter: The counter value to validate against. - :raises cryptography.exceptions.InvalidToken: This is raised when the supplied HOTP - does not match the expected HOTP. - -Throttling ----------- - -Due to the fact that the HOTP algorithm generates rather short tokens that are 6 - 8 digits -long, brute force attacks are possible. It is highly recommended that the server that -validates the token implement a throttling scheme that locks out the account for a period of -time after a number of failed attempts. The number of allowed attempts should be as low as -possible while still ensuring that usability is not significantly impacted. - -Re-synchronization of the Counter ---------------------------------- - -The server's counter value should only be incremented on a successful HOTP authentication. -However, the counter on the client is incremented every time a new HOTP value is requested. -This can lead to the counter value being out of synchronization between the client and server. - -Due to this, it is highly recommended that the server sets a look-ahead window that allows the -server to calculate the next ``x`` HOTP values and check them against the supplied HOTP value. -This can be accomplished with something similar to the following code. - -.. code-block:: python - - def verify(hotp, counter, look_ahead): - assert look_ahead >= 0 - correct_counter = None - - otp = HOTP(key, 6, default_backend()) - for count in range(counter, counter+look_ahead): - try: - otp.verify(hotp, count) - correct_counter = count - except InvalidToken: - pass - - return correct_counter \ No newline at end of file diff --git a/docs/hazmat/primitives/twofactor.rst b/docs/hazmat/primitives/twofactor.rst new file mode 100644 index 00000000..2b811e1e --- /dev/null +++ b/docs/hazmat/primitives/twofactor.rst @@ -0,0 +1,94 @@ +.. hazmat:: + +Two-factor Authentication +========================= + +.. currentmodule:: cryptography.hazmat.primitives.twofactor + +This module contains algorithms related to two-factor authentication. + +Currently, it contains an algorithm for generating and verifying +one time password values based on Hash-based message authentication +codes (HMAC). + +.. currentmodule:: cryptography.hazmat.primitives.twofactor.hotp + +.. class:: HOTP(key, length, backend) + + HOTP objects take a ``key`` and ``length`` parameter. The ``key`` + should be randomly generated bytes and is recommended to be 160 bits in + length. The ``length`` parameter controls the length of the generated + one time password and must be >= 6 and <= 8. + + This is an implementation of :rfc:`4226`. + + .. doctest:: + + >>> import os + >>> from cryptography.hazmat.backends import default_backend + >>> from cryptography.hazmat.primitives.twofactor.hotp import HOTP + + >>> key = b"12345678901234567890" + >>> hotp = HOTP(key, 6, backend=default_backend()) + >>> hotp.generate(0) + '755224' + >>> hotp.verify(b"755224", 0) + + :param bytes key: Secret key as ``bytes``. This value must be generated in a + cryptographically secure fashion and be at least 128 bits. + It is recommended that the key be 160 bits. + :param int length: Length of generated one time password as ``int``. + :param backend: A + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` + provider. + :raises ValueError: This is raised if the provided ``key`` is shorter 128 bits + or if the ``length`` parameter is not between 6 to 8. + + + .. method:: generate(counter) + + :param int counter: The counter value used to generate the one time password. + :return bytes: A one time password value. + + .. method:: verify(hotp, counter) + + :param bytes hotp: The one time password value to validate. + :param bytes counter: The counter value to validate against. + :raises cryptography.exceptions.InvalidToken: This is raised when the supplied HOTP + does not match the expected HOTP. + +Throttling +---------- + +Due to the fact that the HOTP algorithm generates rather short tokens that are 6 - 8 digits +long, brute force attacks are possible. It is highly recommended that the server that +validates the token implement a throttling scheme that locks out the account for a period of +time after a number of failed attempts. The number of allowed attempts should be as low as +possible while still ensuring that usability is not significantly impacted. + +Re-synchronization of the Counter +--------------------------------- + +The server's counter value should only be incremented on a successful HOTP authentication. +However, the counter on the client is incremented every time a new HOTP value is requested. +This can lead to the counter value being out of synchronization between the client and server. + +Due to this, it is highly recommended that the server sets a look-ahead window that allows the +server to calculate the next ``x`` HOTP values and check them against the supplied HOTP value. +This can be accomplished with something similar to the following code. + +.. code-block:: python + + def verify(hotp, counter, look_ahead): + assert look_ahead >= 0 + correct_counter = None + + otp = HOTP(key, 6, default_backend()) + for count in range(counter, counter+look_ahead): + try: + otp.verify(hotp, count) + correct_counter = count + except InvalidToken: + pass + + return correct_counter \ No newline at end of file -- cgit v1.2.3 From 94c73592a8433b4b9567f0c57c9bedadc0e927f7 Mon Sep 17 00:00:00 2001 From: Ayrx Date: Fri, 21 Feb 2014 10:59:05 +0800 Subject: Added "version added" to docs --- docs/hazmat/primitives/twofactor.rst | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs/hazmat') diff --git a/docs/hazmat/primitives/twofactor.rst b/docs/hazmat/primitives/twofactor.rst index 2b811e1e..9d661612 100644 --- a/docs/hazmat/primitives/twofactor.rst +++ b/docs/hazmat/primitives/twofactor.rst @@ -15,6 +15,8 @@ codes (HMAC). .. class:: HOTP(key, length, backend) + .. versionadded:: 0.3 + HOTP objects take a ``key`` and ``length`` parameter. The ``key`` should be randomly generated bytes and is recommended to be 160 bits in length. The ``length`` parameter controls the length of the generated -- cgit v1.2.3