๐Ÿฑ Lunchbox Hands

TOTP Generator & Validator

Generate and validate time-based one-time passcodes (TOTP)

Generate live time-based one-time passcodes (the 6-digit codes from authenticator apps) from a base32 secret, watch them refresh every 30 seconds, and validate a code against the secret. Handy for testing 2FA flows. All computation runs locally in your browser.

expires in 30s

What this tool computes

It implements TOTP as specified in RFC 6238 with the parameters almost every consumer service uses: HMAC-SHA-1, 6 digits, 30-second time step, starting from the Unix epoch. The secret box accepts Base32; it uppercases what you type, removes spaces, and tolerates trailing = padding. The code recalculates every second from your device's clock, and the counter beside it shows how many seconds the current code has left.

Generate random creates a fresh 20-byte (160-bit) secret, which encodes to exactly 32 Base32 characters โ€” a common size for authenticator setups (16-character, 80-bit secrets are also widespread), and the length RFC 4226 recommends for HMAC-SHA-1.

What it does not do:

  • No SHA-256 or SHA-512, no 8-digit codes, no custom period. Those parameters are fixed.
  • No HOTP (counter-based) mode.
  • No QR code or otpauth:// link, so you can't scan the generated secret into a phone from here; type it in with "enter a setup key" in your app, or build a QR from an otpauth://totp/โ€ฆ?secret=โ€ฆ URI with the QR code generator.
  • No way to pick a different time. Codes are always for "now" on your device's clock.

From secret to six digits

The algorithm is short enough to follow by hand:

  1. Take the current Unix time in seconds and divide by 30, rounding down. That integer is the counter T; it ticks over at :00 and :30 past every minute.
  2. Write T as an 8-byte big-endian number and compute HMAC-SHA-1 of it, using the decoded secret bytes as the key. The result is 20 bytes.
  3. Dynamic truncation: the low 4 bits of the last byte give an offset from 0 to 15. Read the 4 bytes starting there as an integer and clear the top bit.
  4. Take that number modulo 1,000,000 and left-pad it to six digits.

Because the counter, not the code, is what changes, client and server never need to talk to each other after setup โ€” they just need the same secret and roughly the same clock. The longer walk-through in how TOTP 2FA works covers the otpauth URI and why the HMAC step matters; you can experiment with the HMAC itself in the HMAC generator.

Checking an implementation against the RFC test vectors

RFC 6238 Appendix B publishes reference values for the ASCII secret 12345678901234567890. In Base32 that is GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ (we encoded it with our Base32 tool). The RFC lists 8-digit SHA-1 codes; the 6-digit code is simply the last six digits. We ran the same library this page uses, with those fixed timestamps:

  • Unix time 59 โ†’ 287082 (RFC: 94287082)
  • Unix time 1111111109 โ†’ 081804 (RFC: 07081804)
  • Unix time 1234567890 โ†’ 005924 (RFC: 89005924)
  • Unix time 2000000000 โ†’ 279037 (RFC: 69279037)

If your own server-side code produces those values for those times, its truncation and counter encoding are right. Then paste the same secret into the box above and compare against "now": a match there confirms your clock handling too.

Using it to test a 2FA flow

A practical loop when building 2FA: generate a random secret here, store it for a test user in your app, and log in using the code shown. Then try the edges โ€” a code from the previous step (should usually pass), one from a minute ago (should fail), a code with a leading zero, and the same code twice in a row, which a well-built server should reject as a replay even though this validator, which keeps no history, will happily accept it again.

Frequently asked questions

Why does my code not match my authenticator app?

Almost always one of three things. First, the clock: TOTP depends on the current time, so if your computer's clock is off by more than a few seconds near a 30-second boundary, the codes will differ. Second, the settings: this tool only does SHA-1, 6 digits and a 30-second period, which is what Google Authenticator and most sites use, but a service that issues SHA-256 or 8-digit codes will not match. Third, the secret itself: a single mistyped character gives completely different codes.

How long is a code valid when I click Validate?

The validator accepts the current code plus the codes from one 30-second step before and one step after. That tolerance, a window of 1, is the common server-side default and covers small clock drift and the delay of typing a code in. A code from two steps ago is rejected as invalid or expired.

Is it safe to paste a real 2FA secret here?

The calculation happens entirely in your browser and the secret is never sent anywhere. Still, anyone who has the secret can generate your codes forever, so treat it like a password: prefer test secrets, and don't paste a production secret on a shared or untrusted computer.

What does "invalid secret" mean?

The text in the Base32 secret box contains a character outside the Base32 alphabet (A-Z and 2-7). The digits 0, 1, 8 and 9 are the usual culprits, often an O typed as 0 or an I as 1. Spaces are removed automatically and lowercase letters are uppercased, so those are not the problem.

Can a TOTP code start with zero?

Yes. The code is a number from 000000 to 999999, padded to six digits, so 005924 is a perfectly normal code. Systems that store or compare codes as integers and drop the leading zeros are a classic 2FA bug.

Get weekly dev tools and tips