How a TOTP code comes from a setup key and the time, worked through step by step
The short answer. 287082: that is the 6-digit code the RFC 6238 test key gives at 59 seconds past 1 January 1970. Every authenticator does the same three things: divide the time by 30 seconds to get a step number, compute HMAC-SHA1 of that number with the setup key, and cut the result down to six digits. Same key, same clock, same code.
The setup key is the string of letters and digits a site shows under its QR code, labelled "enter this key instead" or similar. It is the shared secret: the site keeps one copy, your app keeps the other, and neither ever sends a code to the other. They agree because they do the same arithmetic on the same key and the same time.
The three steps
- Decode the key. The setup key is Base32: only the letters A to Z and the digits 2 to 7, often shown in groups of four. Decoding turns it into bytes; 20 bytes, 160 bits, is the norm.
- Find the time step. Step = the number of seconds since 1 January 1970 (Unix time), divided by 30, rounded down. It goes up by one every 30 seconds, which is why the code changes.
- HMAC and truncate. Compute HMAC-SHA1 with the key, over the step written as 8 bytes. Take the last 4 bits of the 20-byte result as a position, read the 4 bytes starting there, clear the top bit, and keep the last 6 digits of that number.
Step 3 is HOTP, from RFC 4226. TOTP, RFC 6238, is HOTP with the time step in place of a counter. The defaults almost every app uses are SHA-1, 6 digits and 30 seconds.
A worked example
RFC 6238 publishes a test key so that anyone can check their code. It is the ASCII text 12345678901234567890, which as a setup key reads GEZD GNBV GY3T QOJQ GEZD GNBV GY3T QOJQ. Never test with a real account's key; this one exists to be published.
At 59 seconds of Unix time:
- Step = 59 ÷ 30 = 1.97, rounded down to 1.
- HMAC-SHA1(key, step 1 as 8 bytes) =
75a48a19d4cbe100644e8ac1397eea747a2d33ab. - The last byte is
ab; its last 4 bits areb, which is 11. - The 4 bytes starting at byte 11 (counting from 0) are
c1 39 7e ea. Clearing the top bit makes41 39 7e ea, which is 1,094,287,082. - The last six digits: 287082. With 8 digits it is 94287082, the value printed in RFC 6238's table.
The same key at other times:
| Unix time | Date and time (UTC) | Step | 6-digit code | RFC 6238's 8-digit value |
|---|---|---|---|---|
| 59 | 1970-01-01 00:00:59 | 1 | 287082 | 94287082 |
| 1111111109 | 2005-03-18 01:58:29 | 37037036 | 081804 | 07081804 |
| 1234567890 | 2009-02-13 23:31:30 | 41152263 | 005924 | 89005924 |
| 2000000000 | 2033-05-18 03:33:20 | 66666666 | 279037 | 69279037 |
The 6-digit code is always the last six digits of the 8-digit one, and a leading zero is kept: 081804, not 81804. On the TOTP Generator, press Try the RFC example to load this key and watch its live codes.
How to get a code from a setup key
- Open the 2FA Code Generator or the TOTP Generator. Paste the setup key into the Secret box. Spaces and lower case are fine; an
otpauth://link works too and fills in the settings. - Leave Algorithm on SHA-1, Digits on 6 and Period on 30 s, unless the site says otherwise.
- Read the Current code beside the countdown ring. The Previous and Next codes are shown below it.
- Click the code, or press Ctrl+Enter, to copy it, and paste it before the ring runs out.
To check a code someone else's device made, type it into Test a code. With a drift allowance of 1, the page also accepts the step before and after, and says which one matched: a code from the previous step means that device's clock may be 30 seconds slow.
Keep the key secret
- A setup key is a password. Anyone who has it can make every future code for that account until you reset two-factor login. It is not like a code that expires in 30 seconds.
- Do not store it next to the password. If both sit in the same note or file, someone who finds one finds the other, and the two factors have become one.
- On this page the key stays in the tab. Codes are computed on your device with Web Crypto. The key is never sent, logged or saved, and it disappears when you close the tab; only the algorithm, digits, period and drift are remembered.
- Use test keys for development. Press New secret for a random 20-byte key, or use the RFC example, rather than a real account's key.
If the code is rejected
- The device clock is wrong. The code depends on the time, so a clock a minute off gives a code from another step. Turn on automatic date and time on the phone or computer.
- "Not a Base32 character". The key has a 0, 1, 8 or 9, which Base32 does not use. The page suggests the likely letter: 0 is probably O, 1 is I or L, 8 is B.
- "This secret is only N bytes". The key is too short; at least 16 Base32 characters (10 bytes) are needed. A character was probably missed when copying.
- The settings differ. A site that uses SHA-256, 8 digits or 60 seconds gives different codes, and many authenticator apps ignore those settings. Compare the app with the page before relying on it.
Questions people ask
How is a TOTP code calculated?
The time in seconds since 1970 is divided by 30 and rounded down to give a step number. HMAC-SHA1 of that step, keyed with the setup key, gives 20 bytes; RFC 4226's dynamic truncation picks 4 of them by the last byte's low 4 bits and keeps six digits. The RFC 6238 test key at 59 seconds gives 287082.
Can I get my 2FA code without my phone?
Yes, if you have the setup key: paste it into a TOTP generator and it shows the same code as the app, because the code depends only on the key and the time. Treat that as a backup, not a habit. A key copied onto a computer is a second place someone could find it.
Is a 2FA setup key the same as a password?
In practice, yes. Anyone with the setup key can generate valid codes for the account for as long as two-factor login stays set up, so it needs the same care as a password. Keep it out of screenshots, chats and the file that holds the password, and reset two-factor login if it leaks.
Why does my authenticator code keep changing?
The code is tied to a 30-second time step. When the step number goes up, the input to the HMAC changes and so does the code. Servers usually accept the step before and after as well, so a code typed a few seconds late still works. A code that never works points to a wrong clock or key.
What characters can a TOTP setup key contain?
Only the 26 letters A to Z and the digits 2 to 7: that is Base32, RFC 4648. There is no 0, 1, 8 or 9, because they look like O, I, L and B. Spaces and dashes are for reading only, lower case means the same, and = padding at the end is ignored.
Sources
Checked 15 Oct 2026:
- IETF RFC 6238, TOTP: Time-Based One-Time Password Algorithm (Appendix B, the test key and the 8-digit SHA-1 values above).
- IETF RFC 4226, HOTP: An HMAC-Based One-Time Password Algorithm (dynamic truncation; the 160-bit key recommendation).
- IETF RFC 4648, The Base16, Base32, and Base64 Data Encodings (the Base32 alphabet).
- Every step and code on this page was computed with the TOTP Generator's own functions; the HMAC bytes with Node.js's crypto module, and its truncation with the tool's.