aboutsummaryrefslogtreecommitdiffstats
path: root/docs/hazmat/primitives/twofactor.rst
diff options
context:
space:
mode:
authorAyrx <terrycwk1994@gmail.com>2014-02-18 12:33:55 +0800
committerAyrx <terrycwk1994@gmail.com>2014-02-21 11:13:35 +0800
commit8c1ad596b02f89cde6040e8626e07ca352182130 (patch)
tree49a82f2d0dae83dbda4fa0726071dbc04dbd3936 /docs/hazmat/primitives/twofactor.rst
parent26d276f2a9f7b1ca155cb7cced139b2d15baf272 (diff)
downloadcryptography-8c1ad596b02f89cde6040e8626e07ca352182130.tar.gz
cryptography-8c1ad596b02f89cde6040e8626e07ca352182130.tar.bz2
cryptography-8c1ad596b02f89cde6040e8626e07ca352182130.zip
Changed module name from otp to twofactor.
Diffstat (limited to 'docs/hazmat/primitives/twofactor.rst')
-rw-r--r--docs/hazmat/primitives/twofactor.rst94
1 files changed, 94 insertions, 0 deletions
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