HMAC-based one-time password
This is a part of Multifactor authentication series
HMAC-based one-time password (HOTP) is a one-time password (OTP) algorithm based on hash-based message authentication codes (HMAC). It uses a counter that is incremented after each use to prevent replay attacks. Hash is generated using a shared secret key and a counter value, which should be synchronized between the server and the client. During activation, the server generates a random secret key and shares it with the client. On each authentication, the client generates a hash value using the secret key and the counter value. The server does the same and compares the values.
Playground
Full requirements for HOTP are described in RFC.
- HOTP MUST be at least 6-digit value
- It is RECOMMENDED that HOTP value be 'numeric only'
- The length of the shared secret MUST be at least 128 bits
- RECOMMENDED shared secret length is 160 bits
It is not directly stated in the RFC, but HOTP implementations in popular apps like Google Authenticator and Authy use Base-32 encoding to represent the secret key.
Base-32 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. It is defined in RFC 4648.
The Base-32 alphabet is a special set of characters that can be represented using 5 bits each and selected to avoid characters that look similar when printed:
Value | Encoding | Value | Encoding | Value | Encoding |
---|---|---|---|---|---|
0 | A | 11 | L | 22 | W |
1 | B | 12 | M | 23 | X |
2 | C | 13 | N | 24 | Y |
3 | D | 14 | O | 25 | Z |
4 | E | 15 | P | 26 | 2 |
5 | F | 16 | Q | 27 | 3 |
6 | G | 17 | R | 28 | 4 |
7 | H | 18 | S | 29 | 5 |
8 | I | 19 | T | 30 | 6 |
9 | J | 20 | U | 31 | 7 |
10 | K | 21 | V | (pad) | = |
Please notice, that Base-32 only uses uppercase letters and avoids digits 0 and 1, as they can be confused with the letters O and I.
As stated above in requirements, the secret is a random Base-32 string of at least 128 bits. But during OTP calculation secret is treated as a byte array converted from ASCII string. So, length should be divisible by 8.
In this section, we introduce the notation and describe the HOTP algorithm basic blocks - the base function to compute an HMAC-SHA-1 value and the truncation method to extract an HOTP value.
Notation and Symbols
A string always means a binary string, meaning a sequence of zeros and ones.
If s
is a string, then |s|
denotes its length.
If n
is a number, then |n|
denotes its absolute value.
If s
is a string, then s[i]
denotes its i-th bit. Numeration of bits starting at 0, so s = s[0]s[1]...s[n-1]
where n = |s|
is the length of s
.
Let StToNum
(String to Number) denote the function that as an input string s
returns the number whose binary representation is s
. (For example, StToNum(110) = 6.)
List of symbols used in the algorithm:
Symbol | Description |
---|---|
C | 8-byte counter value, the moving factor. This counter MUST be synchronized between the HOTP generator (client) and the HOTP validator (server). |
K | shared secret between client and server; each HOTP generator has a different and unique secret K. |
T | throttling parameter: the server will refuse connections from a user after T unsuccessful authentication attempts. |
s | resynchronization parameter: the server will attempt to verify a received authenticator across s consecutive counter values. |
D | HOTP value |
Description
The HOTP algorithm is based on an increasing counter value and a static symmetric key known only to the token and the validation service. In order to create the HOTP value HMAC-SHA-1 algorithm is used.
As the output of the HMAC-SHA-1 calculation is 160 bits, value must be truncated to something that can be easily entered by a user.
HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))
Truncate(String) = String[StToNum(OffsetBits)]...String[StToNum(OffsetBits)+3]
OffsetBits
is the low-order 4 bits of String[19]
(last byte)
The Key (K
), the Counter (C
) are hashed high-order byte first.
The HOTP values generated by the HOTP generator are treated as big endian.
HMAC-SHA-1(K,C)
is a 20-byte string
Truncate
is a dynamic truncation, which is 31-bit string.
The most significant bit of Truncate is dropped to avoid confusion about signed vs. unsigned modulo computations
Truncating the HMAC-SHA-1 value to a shorter value makes a brute force attack possible. Therefore, the authentication server needs to detect and stop brute force attacks.
It is RECOMMENDed to set a throttling parameter T
, which defines the maximum number of possible attempts for One-Time Password validation. The validation server manages individual counters per HOTP device in order to take note of any failed attempt. It is RECOMMENDed for T
not to be too large, particularly if the resynchronization method used on the server is window-based, and the window size is large. T
SHOULD be set as low as possible, while still ensuring that usability is not significantly impacted.
The delay or lockout schemes MUST be across login sessions to prevent attacks based on multiple parallel guessing techniques.
Although the server's counter value is only incremented after a successful HOTP authentication, the counter on the token is incremented every time a new HOTP is requested by the user. Because of this, the counter values on the server and on the token might be out of synchronization.
It is RECOMMENDed to set a look-ahead parameter s
on the server, which defines the size of the look-ahead window. In a nutshell, the server can recalculate the next s
HOTP-server values, and check them against the received HOTP client.
Synchronization of counters in this scenario simply requires the server to calculate the next HOTP values and determine if there is a match. Optionally, the system MAY require the user to send a sequence of (say, 2, 3) HOTP values for resynchronization purpose, since forging a sequence of consecutive HOTP values is even more difficult than guessing a single HOTP value.
The upper bound set by the parameter s
ensures the server does not go on checking HOTP values forever (causing a denial-of-service attack) and also restricts the space of possible solutions for an attacker trying to manufacture HOTP values. s
SHOULD be set as low as possible, while still ensuring that usability is not impacted.
Reference
Up next