99 lines
4.1 KiB
ReStructuredText
99 lines
4.1 KiB
ReStructuredText
One Time Passwords
|
|
========================
|
|
|
|
.. versionadded:: 2.2.0
|
|
|
|
One time password schemes are a user authentication method that relies on a
|
|
fixed secret key which is used to derive a sequence of short passwords, each of
|
|
which is accepted only once. Commonly this is used to implement two-factor
|
|
authentication (2FA), where the user authenticates using both a conventional
|
|
password (or a public key signature) and an OTP generated by a small device such
|
|
as a mobile phone.
|
|
|
|
Botan implements the HOTP and TOTP schemes from RFC 4226 and 6238.
|
|
|
|
Since the range of possible OTPs is quite small, applications must rate limit
|
|
OTP authentication attempts to some small number per second. Otherwise an attacker
|
|
could quickly try all 1000000 6-digit OTPs in a brief amount of time.
|
|
|
|
HOTP
|
|
^^^^^^
|
|
|
|
HOTP generates OTPs that are a short numeric sequence, between 6 and 8 digits
|
|
(most applications use 6 digits), created using the HMAC of a 64-bit counter
|
|
value. If the counter ever repeats the OTP will also repeat, thus both parties
|
|
must assure the counter only increments and is never repeated or
|
|
decremented. Thus both client and server must keep track of the next counter
|
|
expected.
|
|
|
|
Anyone with access to the client-specific secret key can authenticate as that
|
|
client, so it should be treated with the same security consideration as would be
|
|
given to any other symmetric key or plaintext password.
|
|
|
|
.. cpp:class:: HOTP
|
|
|
|
Implement counter-based OTP
|
|
|
|
.. cpp:function:: HOTP(const SymmetricKey& key, const std::string& hash_algo = "SHA-1", size_t digits = 6)
|
|
|
|
Initialize an HOTP instance with a secret key (specific to each client),
|
|
a hash algorithm (must be SHA-1, SHA-256, or SHA-512), and the number of
|
|
digits with each OTP (must be 6, 7, or 8).
|
|
|
|
In RFC 4226, HOTP is only defined with SHA-1, but many HOTP
|
|
implementations support SHA-256 as an extension. The collision attacks
|
|
on SHA-1 do not have any known effect on HOTP's security.
|
|
|
|
.. cpp:function:: uint32_t generate_hotp(uint64_t counter)
|
|
|
|
Return the OTP associated with a specific counter value.
|
|
|
|
.. cpp:function:: std::pair<bool,uint64_t> verify_hotp(uint32_t otp, \
|
|
uint64_t starting_counter, size_t resync_range = 0)
|
|
|
|
Check if a provided OTP matches the one that should be generated for
|
|
the specified counter.
|
|
|
|
The *starting_counter* should be the counter of the last successful
|
|
authentication plus 1. If *resync_resync* is greater than 0, some number
|
|
of counter values above *starting_counter* will also be checked if
|
|
necessary. This is useful for instance when a client mistypes an OTP on
|
|
entry; the authentication will fail so the server will not update its
|
|
counter, but the client device will subsequently show the OTP for the
|
|
next counter. Depending on the environment a *resync_range* of 3 to 10
|
|
might be appropriate.
|
|
|
|
Returns a pair of (is_valid,next_counter_to_use). If the OTP is invalid
|
|
then always returns (false,starting_counter), since the last successful
|
|
authentication counter has not changed.
|
|
|
|
|
|
TOTP
|
|
^^^^^^^^^^
|
|
|
|
TOTP is based on the same algorithm as HOTP, but instead of a counter a
|
|
timestamp is used.
|
|
|
|
.. cpp:class:: TOTP
|
|
|
|
.. cpp:function:: TOTP(const SymmetricKey& key, const std::string& hash_algo = "SHA-1", \
|
|
size_t digits = 6, size_t time_step = 30)
|
|
|
|
Setup to perform TOTP authentication using secret key *key*.
|
|
|
|
.. cpp:function:: uint32_t generate_totp(std::chrono::system_clock::time_point time_point)
|
|
|
|
.. cpp:function:: uint32_t generate_totp(uint64_t unix_time)
|
|
|
|
Generate and return a TOTP code based on a timestamp.
|
|
|
|
.. cpp:function:: bool verify_totp(uint32_t otp, std::chrono::system_clock::time_point time, \
|
|
size_t clock_drift_accepted = 0)
|
|
|
|
.. cpp:function:: bool verify_totp(uint32_t otp, uint64_t unix_time, \
|
|
size_t clock_drift_accepted = 0)
|
|
|
|
Return true if the provided OTP code is correct for the provided
|
|
timestamp. If required, use *clock_drift_accepted* to deal with
|
|
the client and server having slightly different clocks.
|