Cryptography

How TOTP Authenticator Apps Actually Work

June 14, 2026 9 min read Haven Team

Turn off Wi-Fi and cellular, open your authenticator app, and the six-digit code still appears — and it still works when you log in. That's the giveaway: the code was never sent to you. Your phone computed it from two ingredients it already had, a shared secret and the current time, using math that the server runs independently and gets the same answer. Here's exactly how.


Most people treat the rotating six-digit code as a small magic trick. It isn't magic, and the design is genuinely elegant — a standardized algorithm that turns "prove you have this secret" into "prove you have this secret right now" without any network round-trip at code-generation time. The standard is TOTP, the Time-Based One-Time Password algorithm, defined in RFC 6238, which itself builds on the older HOTP (HMAC-Based One-Time Password) from RFC 4226.

Understanding it removes a lot of confusion about what 2FA does and doesn't protect, and why some failure modes (clock drift, the dreaded "code already used") happen.

The Shared Secret: Where It All Starts

When you scan a QR code to set up an authenticator, you are not registering an account in the usual sense. You are copying a shared secret — a random string of bytes — from the server into your app. That QR code encodes a URI that looks roughly like this:

otpauth://totp/Example:alice@example.com
  ?secret=JBSWY3DPEHPK3PXP
  &issuer=Example
  &algorithm=SHA1
  &digits=6
  &period=30

The secret is the only part that matters cryptographically — it's a Base32-encoded random key. After setup, both your phone and the server hold a copy of this same secret. From that moment on, no further communication is needed for code generation. Both sides can independently derive the same sequence of codes forever, because they share the key and they share the clock.

Why this is "something you have"

The secret living on your device is the second factor. The codes are just disposable proofs that the device holding the secret is present. If an attacker never gets the secret, they can never produce valid future codes — even after watching you enter ten of them.

Step One: Turn Time Into a Counter

TOTP is really HOTP with the counter replaced by time. HOTP increments a counter every use; TOTP derives the counter from the clock so both sides stay in sync automatically. The formula is:

T = floor((current_unix_time - T0) / period)

With the usual defaults — T0 = 0 (the Unix epoch) and period = 30 seconds — this just means: take the current Unix timestamp, divide by 30, drop the remainder. The result T is a counter that increases by one every 30 seconds and is identical on any two devices with a roughly correct clock. That shared, time-derived counter is the synchronization trick at the heart of the whole scheme.

Step Two: HMAC the Counter With the Secret

Now both sides compute a keyed hash. They take the counter T (encoded as an 8-byte value) and run it through HMAC using the shared secret as the key:

hash = HMAC-SHA1(secret, T)   // 20 bytes of output

HMAC is a construction that combines a secret key with a message through a hash function in a way that's secure against forgery — you cannot produce a valid HMAC for a new input without knowing the key. The default hash is SHA-1, which is considered broken for collision resistance but remains safe in the HMAC construction, which is why RFC 6238 still permits it (SHA-256 and SHA-512 are also allowed). The output is a 20-byte string that looks completely random and changes entirely whenever the counter ticks over.

Step Three: Squeeze 20 Bytes Into 6 Digits

A 20-byte hash isn't a human-friendly code. TOTP uses a clever step called dynamic truncation to extract a number deterministically:

  1. Take the last byte of the hash and read its low 4 bits as a number from 0–15. Call this the offset.
  2. Starting at that offset, read the next 4 bytes from the hash.
  3. Mask off the top bit (to avoid signed-integer issues) to get a 31-bit number.
  4. Take that number modulo 106 to get a 6-digit code (pad with leading zeros if needed).

Using the hash itself to choose where to read from is what makes it "dynamic" — it spreads which bytes get used, so the output draws on the whole hash rather than a fixed window. The result is a 6-digit code that both your phone and the server compute identically, with no communication between them.

The server doesn't store your codes or send them. It runs the exact same calculation you do and checks whether its answer matches what you typed. Two machines, one secret, one clock, same math.

Why Verification Is a Little Forgiving

If TOTP required your phone's clock to match the server's to the second, it would fail constantly. Two real-world accommodations make it usable:

The trade-off is real: a wider window is more forgiving of drift but gives an attacker slightly more time to use a phished code. Most implementations keep it tight for that reason.

What TOTP Protects — and What It Doesn't

TOTP is a major upgrade over passwords alone, and a clear improvement over SMS codes, which can be intercepted via SIM swapping or SS7 attacks. But it has a specific, important weakness:

Threat Does TOTP stop it?
Reused/leaked password (credential stuffing) Yes — the password alone is useless without the code.
SMS interception / SIM swap Yes — codes are generated on-device, never sent over the network.
Database breach of the service Partly — if the server stores secrets in plaintext, a breach exposes them. Secrets should be encrypted at rest.
Real-time phishing (attacker relays your code instantly) No — you can be tricked into typing a live code into a fake site that forwards it.

That last row is why TOTP is not the end of the road. Because the code is just a number a human can be tricked into typing elsewhere, a convincing phishing page can relay it in real time. The defense is phishing resistance: cryptographic challenge-response bound to the real site's origin. That's exactly what passkeys and hardware security keys provide — the browser will only complete the handshake with the legitimate domain, so there's no code to phish.

Practical Takeaways

TOTP is a beautiful example of cryptographic minimalism: one shared secret, one shared clock, and a hash function turn into a continuously rotating proof of possession, with no server round-trip and no network dependency. Knowing what it does well — and the one thing it doesn't — lets you layer it correctly. For a broader comparison of factor types, see our guide to two-factor authentication methods compared.

Try Haven free for 15 days

Encrypted email and chat in one app. No credit card required.

Get Started →