How TOTP Authenticator Codes Work: The Shared Secret and the Clock
A plain-English walkthrough of how TOTP turns a Base32 secret and the current time into a 6-digit authenticator code every 30 seconds, fully offline.
How TOTP Authenticator Codes Work: The Shared Secret and the Clock
Every time you open an authenticator app, a fresh six-digit number appears, counts down, and is replaced by another. The number is never sent to you. Your phone is not asking a server what to display. It computes the code itself, the server computes the same code on its own, and the two happen to agree because they share one secret and they both watch the same clock. That is the whole idea behind a time-based one-time password, or TOTP, and once you see the two ingredients it stops feeling like magic.
Two ingredients: a secret and the time
When you turn on two-factor authentication, the site generates a random key and shows it to you twice: as a QR code, and as a string of letters A to Z and digits 2 to 7. That string is the Base32 secret. The QR code is just an otpauth:// link wrapping the same secret along with a few options. Your authenticator scans it, decodes the Base32 back into raw bytes, and stores it. The server keeps its own copy of the identical secret.
From that point on, neither side ever sends the secret again. The only other thing both sides need is the current time, and a clock is something every device already has. A secret that both parties hold plus a value that both parties can read independently is enough to produce a number that only they can reproduce. No network round trip, no message in flight to intercept.
The actual computation, step by step
Here is the concrete part. TOTP hashes the Base32 secret with the current 30-second time step to produce the six-digit code, so both sides compute the same value without ever communicating. Spelled out:
- Take Unix time (seconds since 1970) and divide it by the period, 30 seconds by default. Floor the result. This is the time counter. At 12:00:14 and at 12:00:29 the counter is identical, because both land in the same 30-second window.
- Encode that counter as an 8-byte value and run HMAC-SHA1 over it, keyed by the raw bytes of your secret. HMAC is a keyed hash: same key and same input always give the same 20-byte output, and you cannot run it backwards to recover the key.
- Dynamic-truncate that 20-byte digest down to a number, then take it modulo one million to get six digits. Pad with leading zeros if needed.
Because the counter only changes when a new 30-second window starts, the code is stable for the whole window and then rolls over. Your phone and the server, looking at the same wall clock, land on the same counter and therefore the same code. They never had to talk.
A worked example you can reproduce
The RFC 6238 specification ships test vectors, which makes this easy to check. Take the secret GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ. At Unix time 59 seconds, the counter is 59 divided by 30 floored, which is 1. Run HMAC-SHA1 over that counter with the secret, truncate to eight digits, and you get 94287082. Anyone, anywhere, who runs the same algorithm with that secret and that timestamp gets 94287082 too. That reproducibility is the point: it is not a random number, it is a deterministic function of (secret, time).
Now the practical worry: what if the clocks disagree? Phones drift, servers drift, and a few seconds of skew is normal. TOTP handles this gracefully. When the server receives a code, it does not only compute the code for the current window. It also checks the adjacent windows, usually one step on each side. So if your phone is 20 seconds ahead and shows you the code for the next window, the server still accepts it because it tried that window too. This tolerance is why a code that looks "early" or "late" by a few seconds still logs you in, and why authenticator apps occasionally nudge you to re-sync the clock if drift grows past that window.
If you want to watch this happen, paste a Base32 secret into the TOTP generator and you will see the live six-digit code, the seconds left in the current window, and the code that comes next, all updating in place. The "next" code is exactly what the server's forward-window check would also accept.
Why it works with no internet at all
The reason TOTP works on a plane, in a tunnel, or on a freshly wiped laptop is that nothing in the algorithm needs the network. The secret is already on the device. The time comes from the local clock. HMAC-SHA1 is pure arithmetic. There is no server to call, no challenge to fetch, no token to refresh. The server is doing the same offline computation on its side, and the two results meet only when you finally type the code in.
I lean on this constantly. The first time I set up 2FA on a critical account, I did not trust that the QR scan had transferred the secret correctly, so I pasted the same Base32 string into a generator on my laptop and watched whether its code ticked in lockstep with my phone, second for second. They matched, which told me both copies of the secret were identical and I would not lock myself out at the next login. It is a thirty-second sanity check that has saved me a panicked recovery flow more than once.
The secret stays on your device
This is the part worth internalizing. The six-digit code is disposable and travels over the wire every login, but the secret never moves. It is set once, during enrollment, and from then on it lives on your phone and the server and nowhere else. A good in-browser generator honors the same rule: the Base32 decode, the HMAC over the time counter via the native WebCrypto API, the truncation, and the countdown all run inside the tab. The secret is never uploaded, never logged, and is deliberately kept out of any shareable URL, so a link you send a colleague carries only the harmless digit-count and period options, never your key.
That local-only design is also why you should still be careful. A browser is a shared space where extensions and onlookers can see what you type, so a generator like this is for a throwaway test secret, for debugging a 2FA integration, or for recovery on a machine you trust, not for parking the secret that guards a live production account. For that, keep the key in a dedicated authenticator app or a hardware token. If you are building auth yourself, related primitives like HMAC generation and the broader topic of generating and storing keys are worth understanding alongside TOTP, because the strength of the whole scheme rests on that one secret staying secret.
Once the two ingredients click, the rest follows: a shared secret set once, a clock both sides already read, a keyed hash that turns those into a six-digit number, and a small tolerance window that forgives the inevitable drift. No magic, just arithmetic that two parties run separately and trust to agree.
Made by Toolora · Updated 2026-06-13