TOTP and HOTP: How Authenticator Apps Work
TOTP and HOTP are the two standardized algorithms that generate the six-digit codes shown in authenticator apps. Both produce a short one-time password from a secret shared between your device and a server, but they differ in what drives the code forward: HOTP uses an incrementing counter, while TOTP uses the clock. Understanding these mechanics explains why the codes change, why they occasionally fail to validate, and what an attacker can and cannot do with them.
The Shared Secret
Every one-time password scheme begins with a secret key that both the authenticator and the server hold. During enrollment the server generates a random secret, usually 160 bits, and delivers it to the authenticator, most often as a QR code encoding an otpauth:// URI.
A typical provisioning URI looks like this:
otpauth://totp/K0G:alice@example.com?secret=JBSWY3DPEHPK3PXP&issuer=K0G&algorithm=SHA1&digits=6&period=30
The secret is Base32-encoded, the issuer and account label identify the entry, and the remaining parameters describe how codes are derived. After scanning, both sides possess the same secret and never transmit it again. This is why a leaked authenticator database, or a phished QR code, is so damaging: whoever holds the secret can generate every future code.
HOTP: Counter-Based One-Time Passwords
HOTP, defined in RFC 4226, derives each code from the shared secret and a moving counter value. The counter is just an integer that increments by one every time a code is consumed.
The core computation is:
- Take the secret
Kand the 8-byte counterC. - Compute
HMAC-SHA1(K, C), producing a 20-byte hash. - Use the low four bits of the last byte as an offset into the hash (dynamic truncation).
- Read four bytes starting at that offset, mask off the top bit, and take the result modulo 10^digits.
- Format the number with leading zeros to the required length, typically six digits.
Because the counter only advances when a code is used, the server and authenticator can drift out of sync if a user generates codes that are never submitted. To tolerate this, servers accept a small look-ahead window, checking the next several counter values. If a code matches counter C+3, the server resynchronizes to that point.
TOTP: Time-Based One-Time Passwords
TOTP, defined in RFC 6238, is a variation of HOTP that replaces the manual counter with a value derived from the clock. This removes the synchronization burden of tracking used codes.
The counter is computed as:
T = floor((unix_time - T0) / X)
Here T0 is usually 0 (the Unix epoch) and X is the time step, conventionally 30 seconds. The resulting T is fed into the same HOTP algorithm as the counter. Every 30 seconds T increments, so a fresh code appears without any interaction.
Handling Clock Skew
Because TOTP depends on time, the device and server clocks must roughly agree. To absorb small differences and network latency, servers validate codes from adjacent time steps, commonly one step before and one step after the expected value. A wider window improves usability but shortens the effective attack time an attacker must beat, so it is a deliberate trade-off. Authenticator apps rely on the device clock, which is why a badly set phone clock causes every code to be rejected.
Why the Codes Are Safe to Show
A one-time password is derived with an HMAC, a keyed hash that is a one-way function. Observing a valid code does not reveal the secret, because reversing the HMAC to recover K is computationally infeasible. This is what allows a code to be displayed on screen and typed into a form without exposing the underlying key.
Two server-side practices keep the scheme sound:
- Single use. A consumed code must be rejected if replayed within its validity window, so an attacker who shoulder-surfs one code cannot reuse it.
- Rate limiting. Six digits mean only a million possibilities. Without throttling and lockout, an attacker could brute-force a code, so servers must cap attempts.
Limitations and Threats
TOTP and HOTP defend well against password reuse, credential-database leaks, and offline guessing, which makes them a solid second factor in multi-factor authentication. They do not, however, resist real-time phishing. Because the code is a short string the user types, a fraudulent site or proxy can capture a valid code and immediately relay it to the legitimate server within the validity window.
Key weaknesses to keep in mind:
- Phishing. Users can be tricked into entering a live code on a fake page.
- Secret theft. Malware or a compromised backup that exposes the seed defeats the scheme entirely.
- Shared-secret model. The server stores a secret capable of generating codes, so a server breach can expose seeds unless they are encrypted at rest.
For threats where phishing resistance matters, hardware-backed public-key methods such as FIDO2 and WebAuthn are stronger, because no reusable secret is ever typed or transmitted. Many platforms offer both, using TOTP as a broadly compatible option and security keys for high-value accounts. You can explore related defensive topics on K0G.
Key Takeaways
- HOTP derives codes from a shared secret and an incrementing counter; TOTP replaces the counter with a time-based value.
- Both use HMAC with dynamic truncation, so a displayed code never reveals the underlying secret.
- Servers tolerate counter drift and clock skew with small validation windows, trading usability against attack surface.
- One-time passwords resist reuse and offline guessing but remain vulnerable to real-time phishing and secret theft.
- Protect the shared secret at rest, enforce single use, and rate-limit attempts to keep the scheme secure.