Time-based one-time passwords
The conceptHow your authenticator app knows the right code with no internet
Your phone and the website each work out the same code on their own. Nothing is sent between them. When you scan the setup QR code, both store the same secret key, a string of random bytes.
Every 30 seconds, both sides turn the time into a counter: Unix time divided by 30, rounded down. They hash it with the key using HMAC, a hash only the key holder can reproduce, then cut it to six digits.
What it’s forTurns a shared secret key and the current time into a short code that both sides can compute.
code = Truncate(HMAC(K, ⌊t / 30⌋)) mod 10⁶
- K
- the secret key shared once through the setup QR code
- t
- current Unix time in seconds since 1 January 1970
- ⌊t / 30⌋
- the time-step counter, which goes up by 1 every 30 seconds
- Truncate
- picks 4 bytes of the hash and reads them as a whole number
What it givesA six-digit code that stays the same for 30 seconds and then changes.
- t = 1,000,000,000 → ⌊t/30⌋ = 33,333,333 (since 30 × 33,333,333 = 999,999,990)
- The counter, and so the code, stays the same until t = 1,000,000,020
- If Truncate gives 2,147,483,647, the code is 2,147,483,647 mod 10⁶ = 483647