ONE-TIME PASSWORDS
What HOTP and TOTP prove, and why the surrounding ceremony matters more than the six digits.
A one-time password looks self-contained. A token displays six digits. A user copies them. A server accepts or rejects the value.
The visible code is only the narrowest part of the mechanism.
Behind it are a long-lived shared secret, a counter or clock, a truncation rule, an acceptance window, an attempt policy, a provisioning process and a recovery path. The code proves that someone obtained a valid output for one moving factor. It does not automatically identify the intended verifier, bind a transaction or prevent real-time relay.
Understanding OTP requires looking past the digits to the authentication ceremony around them.
HOTP is a stateful comparison
HOTP computes an HMAC over an eight-byte counter using a secret shared between authenticator and verifier. Dynamic truncation extracts a 31-bit value, which is reduced modulo a power of ten to obtain the displayed digits.
In simplified form:
HOTP(K, C) = Truncate(HMAC-SHA-1(K, C))
The cryptographic output is deterministic. Security comes from the secrecy of K, the evolution of C and the server’s control of online guesses.
The authenticator increments its counter when it generates a value. The server advances after successful verification. If the user requests several codes without submitting them, the counters diverge. The verifier typically searches a limited look-ahead window and resynchronises when it finds a match.
That window improves usability while increasing the number of acceptable values. It is part of the security calculation, not a harmless implementation detail.
TOTP replaces the counter with time
TOTP derives the moving factor from Unix time and a configured time step, commonly thirty seconds. The same HOTP construction then produces a value for the current interval.
The authenticator and verifier no longer maintain an event counter, but they inherit a clock agreement problem. The verifier may accept adjacent intervals to accommodate drift, entry time and network delay.
A wider window reduces false rejection and increases the number of codes that can succeed. A code can also be captured near the beginning of an interval and remain usable until the verifier’s acceptance window closes.
Time does not remove state. It moves state into clock configuration, drift policy and replay tracking.
RFC 6238 permits HMAC-SHA-256 and HMAC-SHA-512 variants as well as the original HMAC-SHA-1 construction. Interoperability depends on agreeing on the hash, number of digits, time step, initial epoch and secret encoding. A QR provisioning image often carries those parameters, but the convenient transfer format is also a copyable representation of the long-lived seed.
Six digits have a quantifiable bound
A six-digit value contains one million possibilities. Cryptographic unpredictability makes random guessing the best general strategy, but an online verifier decides how many guesses are available.
RFC 4226 approximates an attacker’s success probability using the number of accepted counter positions, the number of verification attempts and the number of digits:
success ≈ window × attempts / 10^digits
The expression captures an important point. The code length cannot be evaluated separately from:
- rate limiting;
- account lockout or progressive delay;
- the resynchronisation or time window;
- parallel verification endpoints;
- whether the same code is accepted more than once;
- monitoring and response.
Eight digits reduce online guessing probability, but do not fix phishing, seed theft or a verifier that accepts unlimited attempts.
The seed is the real credential
The displayed code expires. The shared secret persists.
Anyone who obtains the seed and moving factor can generate the same OTPs as the legitimate authenticator. This makes seed generation, distribution, storage, backup and revocation central to the design.
A verifier typically needs access to the seed or to a service capable of reproducing the expected output. Unlike public-key authentication, verification does not use a public value that can be disclosed freely. A compromise of the validation database can compromise an entire population of authenticators.
Useful controls include:
- unique independently generated secrets per authenticator;
- generation inside an appropriate cryptographic boundary;
- encrypted transport under a separate provisioning key;
- restricted validation interfaces instead of raw seed retrieval;
- separation between enrolment and authentication services;
- inventory of every active copy;
- revocation and replacement procedures;
- auditable import, export and backup ceremonies.
An HSM can protect server-side seeds, but the surrounding application still controls account binding, acceptance windows and recovery. Hardware custody does not define the ceremony.
Provisioning can create the first clone
Software authenticators are commonly enrolled by scanning a QR code containing a URI with the account, issuer, secret and algorithm parameters.
The method is interoperable and convenient. It also means that anyone who photographs, logs, caches or later redisplays the QR code can create another authenticator with the same seed.
A sound provisioning flow should answer:
- Who is authorised to request a new seed?
- How is the enrolment channel authenticated?
- Is the QR representation shown only once?
- Can it appear in browser history, support tooling or screenshots?
- How is successful binding confirmed?
- Are older authenticators revoked or allowed to coexist?
- What evidence is recorded without retaining the secret?
Copying a seed during enrolment defeats the intended possession distinction before the first code is used.
A correct OTP can be relayed
HOTP and TOTP outputs are bearer values during their acceptance window. A verifier usually receives only the digits and account context. The authenticator does not know which website, session or request will consume them.
An attacker can present a convincing login page, collect the password and current OTP, and immediately submit both to the legitimate service. The server sees correct credentials. The user sees a failed or delayed login. The cryptography has worked exactly as specified.
This is why current NIST guidance does not classify manually entered OTP as phishing-resistant. The output is not cryptographically bound to the authenticated verifier or the particular channel.
Short lifetime helps against later reuse. It does not prevent real-time relay.
One-time does not mean one operation
An OTP commonly authenticates access to an account. Applications sometimes extend that result to approval of a payment, credential issuance or administrative action.
Unless the operation details participate in the cryptographic calculation, the code does not state what the user approved. A valid TOTP entered beside a transaction summary proves possession of the seed at that time. The transaction amount, beneficiary and purpose remain UI context supplied by the application.
An attacker who can alter the application flow may substitute those details while preserving the same valid code.
Challenge-response constructions such as OCRA can incorporate a server challenge, session data or transaction information into an HMAC-based response. That can create stronger binding, but only if the authenticator obtains and presents the relevant data through a trustworthy path.
Displaying six digits on a device with no trusted input cannot confirm an arbitrary transaction. The interface determines what the cryptography can mean.
The authenticator form changes the boundary
HOTP was designed with inexpensive and constrained authenticators in mind. RFC 4226 explicitly considers Java smart cards and GSM SIM cards, along with USB devices and other hardware tokens.
The same algorithm can live in different boundaries:
- a dedicated token with a protected seed and display;
- a SIM applet reached through a mobile application or network service;
- a Java Card applet accessed by a reader;
- a secure element inside a phone;
- an ordinary application whose seed is stored in software;
- a synchronised authenticator replicated through a cloud service.
The calculation may be identical while extraction risk, cloning, activation and recovery differ substantially.
A hardware boundary can make the seed harder to extract. It does not stop phishing if the user still reads and retypes an unbound code. Conversely, software storage can be acceptable for some risk levels when combined with device protection and careful account recovery.
The assurance statement must describe the complete authenticator, not only the HOTP or TOTP algorithm.
Replay control belongs to the verifier
A verifier should accept a particular OTP only once while it is valid.
For HOTP, successful acceptance normally advances the server counter beyond the matched value. Concurrent requests must update that state atomically. Otherwise, two verification nodes can accept the same code before observing each other’s update.
For TOTP, the verifier may record the accepted time step for the account and reject a second use. A distributed service needs consistent replay state across nodes. Simply checking that the code belongs to the current window is insufficient.
Retries complicate the user experience. A legitimate user may submit a code, lose the response and try again. The second attempt should not authenticate a new session silently, but the service may need to explain that the value has already been consumed.
Replay resistance is an operational state machine around the algorithm.
Recovery can be weaker than authentication
A strong enrolment and validation design can be bypassed by a weak replacement path.
Common recovery mechanisms include backup codes, help-desk verification, authenticated sessions, identity proofing and binding a new device. Each creates another route to the account.
Recovery should distinguish loss from compromise. If a device is merely unavailable, retaining the old authenticator for a short overlap may help. If the seed may have been copied, every instance derived from it should be invalidated.
The service should record which authenticator was replaced, who authorised the change, which sessions were terminated and whether high-risk operations require a delay or additional confirmation.
An OTP deployment is only as strong as the easiest way to acquire a new seed.
Migration should change the proof, not only the screen
OTP remains useful where simple interoperable authentication must work across constrained devices and manual channels. It is also a mature compatibility mechanism.
For phishing-resistant authentication, migration usually requires a public-key protocol that binds proof to the verifier and session. Replacing SHA-1 with SHA-256 inside TOTP does not add that binding. Increasing from six to eight digits does not add it either.
A transition can support both methods while making the difference visible:
- enrol public-key authenticators under a strongly authenticated session;
- prefer them for new logins;
- restrict OTP fallback by risk and time;
- measure continued OTP use;
- protect recovery from becoming permanent fallback;
- retire server-side seeds when they are no longer required.
This is another form of operational algorithm transition. Supporting a new option is not the same as removing dependence on the old proof.
The ceremony around the code
HOTP and TOTP are compact and carefully specified constructions. They turn a shared secret and moving factor into a short interoperable value suitable for restricted interfaces.
Their limits are equally precise.
The digits do not protect the seed, rate-limit guesses, detect distributed replay, identify the verifier, bind a transaction or secure account recovery. Those properties come from the ceremony built around the calculation.
One-time describes the intended acceptance of the output. It does not describe the complete claim being authenticated.



