Danger
This is a “Hazardous Materials” module. You should
ONLY
use it if you’re
100% absolutely sure that you know what you’re doing because this module is
full of land mines, dragons, and dinosaurs with laser guns.
Two-factor authentication
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).
-
class
cryptography.hazmat.primitives.twofactor.
InvalidToken
[source]
-
This is raised when the verify method of a one time password function’s
computed token does not match the expected token.
-
cryptography.hazmat.primitives.twofactor.hotp.
HOTPHashTypes
-
Added in version 40.0.0.
Type alias: A union of supported hash algorithm types:
SHA1
,
SHA256
or
SHA512
.
-
class
cryptography.hazmat.primitives.twofactor.hotp.
HOTP
(
key
,
length
,
algorithm
,
*
,
enforce_key_length
=
True
)
[source]
-
Added in version 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
.
>>> import os
>>> from cryptography.hazmat.primitives.twofactor.hotp import HOTP
>>> from cryptography.hazmat.primitives.hashes import SHA1
>>> key = os.urandom(20)
>>> hotp = HOTP(key, 6, SHA1())
>>> hotp_value = hotp.generate(0)
>>> hotp.verify(hotp_value, 0)
-
Parameters
:
-
-
key
(
bytes-like
) – 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.
-
length
(
int
) – Length of generated one time password as
int
.
-
algorithm
(
cryptography.hazmat.primitives.hashes.HashAlgorithm
) – A
hashes
instance (must match
HOTPHashTypes
).
-
enforce_key_length
–
A boolean flag defaulting to True that toggles
whether a minimum key length of 128
bits
is enforced. This
exists to work around the fact that as documented in
Issue #2915
,
the Google Authenticator PAM module by default generates 80 bit keys.
If this flag is set to False, the application developer should
implement additional checks of the key length before passing it into
HOTP
.
Added in version 1.5.
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.
-
TypeError
– This is raised if the provided
algorithm
is not
SHA1()
,
SHA256()
or
SHA512()
or if the
length
parameter is not an integer.
-
generate
(
counter
)
[source]
-
-
Parameters
:
-
counter
(
int
) – The counter value used to generate the one time
password.
-
Return bytes
:
-
A one time password value.
-
verify
(
hotp
,
counter
)
[source]
-
-
Parameters
:
-
-
Raises
:
-
cryptography.hazmat.primitives.twofactor.InvalidToken
– This
is raised when the supplied HOTP does not match the expected HOTP.
-
get_provisioning_uri
(
account_name
,
counter
,
issuer
)
[source]
-
Added in version 1.0.
-
Parameters
:
-
-
account_name
(
str
) – The display name of account, such as
'Alice Smith'
or
'alice@example.com'
.
-
issuer
(
str
or
None
) – The optional display name of issuer. This is typically
the provider or service the user wants to access using the OTP
token.
-
counter
(
int
) – The current value of counter.
-
Returns
:
-
A URI string.
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.
def verify(hotp, counter, look_ahead):
assert look_ahead >= 0
correct_counter = None
otp = HOTP(key, 6)
for count in range(counter, counter + look_ahead):
try:
otp.verify(hotp, count)
correct_counter = count
except InvalidToken:
pass
return correct_counter