diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2014-03-08 11:09:49 -0400 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2014-03-08 11:09:49 -0400 |
commit | bf2a9d9545f39ad0dd9b9c9c4aa2f7f2b5669f0f (patch) | |
tree | 083cc465c6fabdb61ff69aadc33b31e8617f2136 /docs/hazmat/primitives/twofactor.rst | |
parent | dee5c25d35c53885698bca42015c9f7bbfb27baa (diff) | |
parent | 78c2f2d2c0a40d20edcaf37c33e91224af3ecbb6 (diff) | |
download | cryptography-bf2a9d9545f39ad0dd9b9c9c4aa2f7f2b5669f0f.tar.gz cryptography-bf2a9d9545f39ad0dd9b9c9c4aa2f7f2b5669f0f.tar.bz2 cryptography-bf2a9d9545f39ad0dd9b9c9c4aa2f7f2b5669f0f.zip |
Merge branch 'master' into idea-bespoke-vectors
* master: (246 commits)
Fixed python3 incompatibility
Removed dependency on setuptools for version check
don't need to move these definitions
conditional NIDs for 0.9.8e
x509 changes for 0.9.8e support
more changes for 0.9.8e support, this time in the ssl.h headers
macro switches in evp for 0.9.8e
bind some error constants conditionally for 0.9.8e support
BIO macro switch for 0.9.8e support
move some nids
conditionally bind AES_wrap/unwrap for 0.9.8e support
Add GPG key fingerprint for lvh
change comparison to be easier to read
ridiculous workaround time
whoops
Missing imports
Convert stuff
Add binding for DSA_new
Fix drop in coverage levels by removing branches
Added check to turn of CC backend for OS X version < 10.8
...
Conflicts:
docs/development/test-vectors.rst
Diffstat (limited to 'docs/hazmat/primitives/twofactor.rst')
-rw-r--r-- | docs/hazmat/primitives/twofactor.rst | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/docs/hazmat/primitives/twofactor.rst b/docs/hazmat/primitives/twofactor.rst new file mode 100644 index 00000000..3912d483 --- /dev/null +++ b/docs/hazmat/primitives/twofactor.rst @@ -0,0 +1,162 @@ +.. 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, algorithm, backend) + + .. versionadded:: 0.3 + + HOTP objects take a ``key``, ``length`` and ``algorithm`` 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 + >>> from cryptography.hazmat.primitives.hashes import SHA1 + >>> key = os.urandom(16) + >>> hotp = HOTP(key, 6, SHA1(), backend=default_backend()) + >>> hotp_value = hotp.generate(0) + >>> hotp.verify(hotp_value, 0) + + :param bytes key: Per-user secret key. This value must be kept secret + 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 HashAlgorithm algorithm: A + :class:`~cryptography.hazmat.primitives.hashes` + provider. + :param backend: A + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` + provider. + :raises ValueError: This is raised if the provided ``key`` is shorter than + 128 bits or if the ``length`` parameter is not 6, 7 or 8. + :raises TypeError: This is raised if the provided ``algorithm`` is not + :class:`~cryptography.hazmat.primitives.hashes.SHA1()`, + :class:`~cryptography.hazmat.primitives.hashes.SHA256()` or + :class:`~cryptography.hazmat.primitives.hashes.SHA512()` or if the + ``length`` parameter is not an integer. + + .. 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 int 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 + +.. currentmodule:: cryptography.hazmat.primitives.twofactor.totp + +.. class:: TOTP(key, length, algorithm, time_step, backend) + + TOTP objects take a ``key``, ``length``, ``algorithm`` and ``time_step`` + parameter. The ``key`` should be randomly generated bytes and is recommended + to be as long as your hash function's output (e.g 256-bit for SHA256). + The ``length`` parameter controls the length of the generated one time + password and must be >= 6 and <= 8. + + This is an implementation of :rfc:`6238`. + + .. doctest:: + + >>> import os + >>> import time + >>> from cryptography.hazmat.backends import default_backend + >>> from cryptography.hazmat.primitives.twofactor.totp import TOTP + >>> from cryptography.hazmat.primitives.hashes import SHA1 + >>> key = os.urandom(16) + >>> totp = TOTP(key, 8, SHA1(), 30, backend=default_backend()) + >>> time_value = time.time() + >>> totp_value = totp.generate(time_value) + >>> totp.verify(totp_value, time_value) + + :param bytes key: Per-user secret key. This value must be kept secret + 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 HashAlgorithm algorithm: A + :class:`~cryptography.hazmat.primitives.hashes` + provider. + :param int time_step: The time step size. The recommended size is 30. + :param backend: A + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` + provider. + :raises ValueError: This is raised if the provided ``key`` is shorter than + 128 bits or if the ``length`` parameter is not 6, 7 or 8. + :raises TypeError: This is raised if the provided ``algorithm`` is not + :class:`~cryptography.hazmat.primitives.hashes.SHA1()`, + :class:`~cryptography.hazmat.primitives.hashes.SHA256()` or + :class:`~cryptography.hazmat.primitives.hashes.SHA512()` or if the + ``length`` parameter is not an integer. + + .. method:: generate(time) + + :param int time: The time value used to generate the one time password. + :return bytes: A one time password value. + + .. method:: verify(totp, time) + + :param bytes totp: The one time password value to validate. + :param int time: The time value to validate against. + :raises cryptography.exceptions.InvalidToken: This is raised when the + supplied TOTP does not match the expected TOTP. |