Zhu Wu's Blog

The world is a fine place and worth fighting for.

One-Time Password Generation

One-time password is deployed widely as a second factor of authentication to enhance security. As a developer, how should we implement OTP generation in the application and what should be taken care of in each implementation?

The most "naive" way is to generate a random string/number, persist it or store it in session, and send it to user before a OTP authentication. The random string/number generation process can be easily implemented upon the random functions provided by the programming language, and the random function used in the implementation needs to be securely random. The server needs to manage the persistence of the OTP and its timeout strategy. Information leakage might be another concern when delivering the OTP to the user.

OTP can also be implemented in an counter-incremental way. The most popular and widely accepted standard is HOTP (as specified in RFC 4226). The server stores a secret key K and a counter C for each user, and the OTP value is derived from HMAC(K, C) by a predefined algorithm. Thus, the server only need to increment the OTP counter each time after each OTP challenge, and it does not need to store the OTP value explicitly. HOTP does not require a delivery, because the user can get OTP from a hardware device or software generator (like Google Authenticator), as long as they share the same secret key and the counter is synchronized. However, in practice, it is hard to synchronze counter between server and the device held by the user since they cannot contact to each other. Therefore, upon an OTP challenge, server tries HOTP(K, C), HOTP(K, C+1), until HOTP(K, C+w), where w is a reasonable window size.

Moreover, OTP can be implemented in a time-synchronized way. The most popular and widely accepted standard is TOTP (as specified in RFC 6238). TOTP is based on HOTP. The server stores a secret key K for each user. Instead of using counter C as in HOTP, TOTP computes OTP value by HOTP(K, timestamp/time step), so the server does not need to maintain a counter. The OTP value remains unchanged for a period of time (as specified by time step), so may impose a replay attack. TOTP can also be generated from a hardware device or software generator (Google Authenticator supports TOTP as well), as long as they share the same secret key and time is synchronized. TOTP may not suitable for explicit delivery. For example, an OTP is computed at the end edge of the time step and it is delivered to user; when user enter the OTP, the server is expecting an OTP from the next time step already, and it results in failure. This behavior is not user friendly.