Generator/What is TOTP
TOTP stands for time-based one-time password. It is the standard behind the rotating six digits in Google Authenticator, Authy, 1Password and every other authenticator app — a number computed from a secret you were given once and the time right now, with nothing sent between your device and the service to agree on it.
At enrollment a service hands you a secret, usually as a QR code. From then on both sides run the same arithmetic on their own: take the current Unix time, divide by 30 to get a step number, run that step number and the secret through HMAC, and squeeze the result down to six digits. Same secret plus same second means same digits, on any device, offline, forever — until someone changes the secret.
That independence is the point. There is no message to intercept, no server to be down, and no carrier in the path the way there is with an SMS code. The cost is that the secret is shared: whoever holds it can produce valid codes, which is why it matters more than the code it produces.
HMAC-SHA1(secret, counter). SHA-256 and SHA-512 are permitted and a few services use them, but SHA-1 is the near-universal default, and its weaknesses as a collision-resistant hash do not apply to HMAC.Nothing in that sequence is reversible in a useful way. A code exposes no practical information about the secret, which is what makes it safe to read one out over the phone — while the secret itself never is.
Appendix B of the specification publishes the values every implementation is expected to reproduce. The secret is the ASCII string 12345678901234567890 — in Base32, GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ — repeated as needed to fill the key length of the stronger hashes. Codes are shown at eight digits, with a 30-second step.
| Unix time | Step | SHA-1 | SHA-256 | SHA-512 |
|---|---|---|---|---|
| 59 | 1 | 94287082 | 46119246 | 90693936 |
| 1111111109 | 37037036 | 07081804 | 68084774 | 25091201 |
| 1111111111 | 37037037 | 14050471 | 67062674 | 99943326 |
| 1234567890 | 41152263 | 89005924 | 91819424 | 93441116 |
| 2000000000 | 66666666 | 69279037 | 90698825 | 38618901 |
| 20000000000 | 666666666 | 65353130 | 77737706 | 47863826 |
If you are checking your own code against these, note the detail that catches most people: the SHA-256 and SHA-512 rows use longer secrets — the same digit string continued to 32 and 64 bytes — not the 20-byte one. Feeding the short secret to SHA-512 produces numbers that look plausible and match nothing.
Because the counter comes from the time, a device whose clock is wrong computes the code for a different step. Roughly thirty seconds of error is enough to produce digits the service rejects from a perfectly correct secret — and the error can be on either side, though servers are rarely the ones that drift.
Servers compensate by accepting a window, typically the step before and after, occasionally wider for services that expect users on bad clocks. That tolerance is also why a code can still work a few seconds after the digits on screen have changed. When codes are refused anyway, the clock is the first thing to check — the rejected-code guide walks through the rest.
The secret is bytes, but it is shown as Base32: the letters A–Z and the digits 2–7, in blocks of 16 or 32 characters. That alphabet exists so a key can be read aloud and typed without confusing 0 with O or 1 with l. Case does not matter, spaces do not matter, and = padding at the end is optional.
The QR code at enrollment is the same secret wrapped in a URI: otpauth://totp/GitHub:[email protected]?secret=JBSWY3DP…&issuer=GitHub. Every parameter that can vary — digits, period, algorithm — travels in that link, which is why importing it is more reliable than typing a key and guessing the rest.
It defends against an attacker holding your password: leaked credentials, reuse across sites, guessing. That covers a large share of real account takeover, which is why it is worth the friction.
It does not defend against you giving the code away. A fake login page can collect password and code and use both on the real site inside the window. It does not help once malware is on the device. And unlike a passkey, the secret exists on the service’s side too, so a breach there can leak seeds for every account that enrolled. Phishing-resistant factors — passkeys, FIDO2 keys — close the first and the last of those, and are worth preferring where a service offers them.