TOTP Code Generator
JBSW Y3DP EHPK 3PXP — 10 bytes — below the 128-bit minimum RFC 4226 requires
The secret never reaches the address bar. A link to this tool carries the digit count and the period, and nothing else.
Code for this step
Reading the clock and asking crypto.subtle for this step’s code…
How this was worked out
- Secret decoded16 base32 characters → 10 bytes (eight characters carry five bytes)
- Counter for this windowfloor(0 ÷ 30) = 0
- One-time valueHMAC-SHA1(secret, counter as eight big-endian bytes) — RFC 4226 §5.3, computed by crypto.subtle
- Truncatedthe low four bits of the last byte pick an offset; four bytes from there, top bit cleared, give a 31-bit number
- Reduced to digitsthat number mod 10^6, padded on the left with zeros — no code yet
The secret is the whole second factor. Anything holding it can produce these digits forever, which is why an authenticator app keeps it and never shows it again after enrolment. Pasting a live secret here is safe only in the sense that nothing on this page leaves your browser: the codes are computed by crypto.subtle on this machine, no request is made, and the secret is kept out of the address bar. Use this to check an enrolment, then treat the secret as used up if it has been anywhere it should not have been.
A code that matches here is evidence about the algorithm, not about the server. A service that rejects it may be enrolled with a different secret, may use a different period, or may have refused the previous step for its own reasons — and a service that accepts a code from four steps ago has a drift window far wider than RFC 6238 suggests, which is worth knowing on its own.
Only HMAC-SHA1 is computed here. RFC 6238 §1.2 permits SHA-256 and SHA-512 as well, and this tool refuses those enrolments rather than showing SHA-1 digits beside them — a code that is confidently wrong is worse than no code. The clock this page reads is your own machine’s: every judgement about drift below is relative to it, so a machine that is itself wrong will report a correct app as drifted.
Where the six digits come from
A time-based one-time password is arithmetic, not magic. RFC 6238 takes the current Unix time, divides it by a step of 30 seconds and throws away the remainder, giving a counter both ends can work out independently. That counter is signed with HMAC-SHA1 under the shared secret, four bytes are selected from the result by the dynamic truncation rule in RFC 4226, and the remainder modulo one million is padded to six digits.
Nothing is transmitted at any point, which is the property that makes the scheme work offline. Your phone and the server never speak to each other; they simply agree on the time and hold the same secret, and this page does the identical sum in your browser using the implementation that guards this site’s own admin login.
Confirming an enrolment before you are locked out
The moment to check a setup is while you still have another way in. Paste the secret shown at enrolment — or the whole otpauth:// URI behind the QR code, which avoids retyping thirty-two characters — and compare what appears here with what the app on your phone is showing. Matching digits mean the secret was transferred correctly and the two clocks agree.
The window of three codes shows why a mismatch is not automatically a failure. Verifiers commonly accept the step either side of the current one, so a code can be a little stale and still be taken. If the code you typed belongs to a neighbouring step, this page says which one and how many seconds out it was, which turns a vague failure into a clock problem you can fix.
When the digits are right and the login still fails
Four things vary between implementations and any of them will produce codes that look plausible and are wrong: the step length, the number of digits, the hash, and the secret itself. Most services use 30 seconds, six digits and SHA-1, and every mainstream authenticator assumes that combination regardless of what the enrolment URI requests.
This tool produces the SHA-1 variant only, and says so rather than guessing when an otpauth URI asks for SHA-256 or SHA-512. That refusal is deliberate: silently showing the wrong digits would send somebody off to re-enrol an authenticator that was working perfectly.
Device clock drift is the other regular cause. A phone whose time is set by hand slips a few seconds a month, and once it drifts past the window a server allows, every code it produces is rejected. Turning on automatic time is the whole fix.
The secret is the second factor
Everything that protects the scheme is in that base32 string. Anything holding it can generate valid codes indefinitely, which is why an authenticator shows the secret once at enrolment and never again, and why a screenshot of a QR code sitting in a photo library is a credential rather than a picture.
RFC 4226 requires at least 128 bits of shared secret and recommends 160, which is the twenty bytes most enrolment screens encode as thirty-two base32 characters. This page computes locally and sends nothing anywhere, but a secret that has been pasted into any tool has been somewhere it was not meant to be — re-enrol rather than assume.
Clock drift, rejected codes and base32
The code here matches my app but the website rejects it. Why?
Usually the account was enrolled with a different secret than the one you pasted, or the service uses a period or digit count other than the default. Check the enrolment URI parameters, and try the code immediately rather than at the end of a step.
Can I use this page instead of an authenticator app?
No, and it is not built to. A browser tab keeps nothing, offers no device lock, and every visit means handling the secret again. Use it to verify an enrolment or to recover from one, then go back to a proper app.
How far out can my clock be before codes stop working?
That is the verifier’s choice, not the standard’s. Accepting one step either side is common, which tolerates roughly a minute of drift in total. Some services allow more, and a service that accepts a code several minutes old has a wider window than it probably intended.
Why is there no 0, 1 or 8 in a secret?
Base32 uses the letters A to Z and the digits 2 to 7 exactly so that no character can be confused with another when read aloud or copied by hand. A zero would be indistinguishable from the letter O on most screens.
What happens to my codes if I lose the phone?
Nothing recovers them except the backup codes issued at enrolment or a second device enrolled at the same time. The secret exists only where it was stored, so print the recovery codes when you set the account up rather than when you need them.