HOTP (RFC 4226) Counter Validator|Test ±N Drift Windows in Your Browser
Generate HMAC-SHA-1 HOTP codes from a Base32 secret and counter, then check whether a received code lands inside the ±N counter window. Reproduce RFC 4226 behaviour from plain inputs, no server required.
💡 About this tool
HOTP (RFC 4226) is a one-time-password scheme whose moving factor is a counter, not the clock. It powers hardware tokens like Yubico's OATH-HOTP slot and counter-based codes that back up SMS. Because it needs no clock alignment, it suits offline devices and environments where time sync is unreliable.
The headache with counter-based OTP is drift. The token's counter increments every time the button is pressed, but the server's counter advances only after a successful login. A user who fans the token a few times pushes the two out of step, and codes stop validating. RFC 4226 absorbs this with a look-ahead window: the server recomputes the next few HOTP values, compares them against the submitted one, and on a hit advances its counter to the matched value + 1.
This validator lays out every code inside that window at once. The current-counter row is highlighted, and the row matching your submitted code is shown in a separate colour — so you can reason about how far ahead a server should accept, or debug a token, without spinning up a backend. It is deliberately separate from time-based TOTP; reach for a TOTP tool when the clock is the moving factor.
🧐 Frequently Asked Questions
How is HOTP different from TOTP? The moving factor differs. HOTP uses an event counter; TOTP uses time. A HOTP code stays valid until it is used, whereas a TOTP code self-expires after 30–60 seconds. This tool is HOTP only.
What format does the shared secret take?
RFC 4648 Base32 (A–Z and 2–7). Spaces and dashes are ignored and trailing = padding is optional. Any character that is not valid Base32 triggers an error.
What does the ±N window mean? The span of codes checked on either side of the current counter. A larger N tolerates more drift but widens the brute-force surface. RFC §7.4 recommends rejecting any counter at or below one already accepted.
Which digit length should I choose? The OTP output length. Google Authenticator uses 6 digits; Yubico tokens are often 8. Match your token's spec.
Where does the computation run? Entirely in your browser via the Web Crypto API; the shared secret you enter is never sent to a server.
📚 Why the dynamic truncation step exists
The clever part of HOTP is dynamic truncation. The last 4 bits of the 20-byte HMAC-SHA-1 output are read as an offset, four bytes are sliced from there, and the top bit is masked to 0 to form a 31-bit integer before the modulo. That high-bit mask is not cosmetic: it sidesteps implementations that would otherwise treat the slice as a signed integer and disagree on the result. RFC 4226 Appendix D pins this down with test vectors — secret 12345678901234567890 yields 755224 at counter 0 and 287082 at counter 1 — so any implementation can be checked line by line. Because the procedure is frozen this precisely, a token and a server from different vendors land on the same code, and the later TOTP standard simply reused the same truncation on top of a time-derived counter.