#4161: How Your Password Manager's 6-Digit Code Actually Works

Your phone and a server generate the same code without ever talking. Here's the elegant math behind it.

Featuring
Listen
0:00
0:00
Episode Details
Episode ID
MWP-4340
Published
Duration
22:29
Audio
Direct link
Pipeline
V5
TTS Engine
chatterbox-regular
Script Writing Agent
deepseek-v4-pro

AI-Generated Content: This podcast is created using AI personas. Please verify any important information independently.

That six-digit code in your authenticator app isn't random, and it's not being transmitted over the network. Your phone and the server are independently computing the exact same deterministic function — same secret, same clock, same hash — in complete silence. They never exchange a single packet after the initial setup.

The system rests on two RFCs from the Initiative for Open Authentication (OATH). RFC 4226 defined the HMAC-based One-Time Password (HOTP) engine in 2005, and RFC 6238 layered time on top of it in 2011 to create TOTP. The core insight is deceptively simple: both devices divide the current Unix time by thirty seconds, round down, feed that number plus a shared secret into HMAC-SHA-1, and produce the same output.

The algorithm works in three clean steps. First, compute HMAC-SHA-1 of the shared secret and the time step, producing a 20-byte hash. Second, dynamically truncate that hash — take the last byte, use its lower four bits as an offset to grab four bytes from the hash, mask off the most significant bit, and you get a 31-bit number. Third, take that number modulo one million and pad to six digits. That's your code.

When things break, it's almost always clock drift. The standard builds in a one-window look-ahead, but if your phone's clock drifts by two minutes, you're four windows off and locked out of every account at once. As for SHA-1 concerns: TOTP doesn't rely on collision resistance. It relies on the pseudorandomness of HMAC, and the truncation step throws away 16 of 20 bytes anyway. Even a theoretical SHA-1 break wouldn't help an attacker recover your secret or predict future codes.

Downloads

Episode Audio

Download the full episode as an MP3 file

Download MP3
Transcript (TXT)

Plain text transcript file

Transcript (PDF)

Formatted PDF with styling

#4161: How Your Password Manager's 6-Digit Code Actually Works

Corn
Daniel sent us this one — he wants to know what's actually happening when his password manager spits out a new six-digit code every thirty seconds. How does the server know which code is valid at that exact moment, without asking? And why does the whole thing occasionally break? He's right that it usually traces back to clock drift, and he wants to know who built this thing and how the math works under the hood.
Herman
The answer is so much more elegant than most people realize. That code isn't random. It's not being transmitted. Your phone and the server are computing the exact same deterministic function — same secret, same clock — in total silence. They never exchange a single packet.
Corn
Two devices, zero communication, perfectly synchronized output. It sounds like a magic trick.
Herman
It does, and the trick is: they both know what time it is. Specifically, Unix time — the number of seconds since midnight, January first, nineteen seventy. They divide that by thirty, round down, and feed the result into a hash function along with a shared secret. Same inputs, same output.
Corn
The server isn't "accepting" your code — it's predicting it.
Herman
It's computing what your code should be, then comparing. If they match, you're in. And that shared secret — the one you scanned from the QR code — is the only thing that makes your thirty-second window different from anyone else's.
Corn
Which means the QR code is just a delivery mechanism. The real crown jewel is that string of characters.
Herman
Base32-encoded, sitting inside what's called an otpauth URI. You could type it by hand if you wanted to. The QR code just saves you from transcribing about thirty characters of what looks like alphabet soup.
Corn
Daniel's right about the bugs. When this breaks, it's almost always clocks drifting apart. Your phone thinks it's time window forty-seven thousand and twelve, the server thinks it's forty-seven thousand and eleven, and suddenly the math doesn't match.
Herman
The standard actually anticipates this. There's a built-in look-ahead window — the server typically accepts codes from the current thirty-second window and the one immediately before it. But if your phone's clock has drifted by two minutes, that's four windows. The system can't compensate, and you're locked out of every account at once.
Corn
Which is a special kind of panic the first time it happens.
Herman
Here's what makes this worth understanding right now. Everyone's talking about passkeys and WebAuthn — and those are better, we'll get to why — but TOTP is still the most widely deployed second factor on the planet. Hundreds of millions of people use it every day. Almost nobody knows what's actually happening under the hood.
Corn
Daniel's prompt gets at something deeper too. He mentions that two-factor authentication is partly a fallback for password reuse — a second lock because humans are going to human. And he's not wrong. But TOTP specifically solves a problem that's genuinely hard: proving you possess a secret without ever sending that secret over the network.
Herman
Your password gets transmitted every time you log in. The TOTP secret never leaves your device. The server has its own copy from when you set it up, and from that point on, both sides just do math.
Corn
Let's unpack that math. Because the algorithm itself is surprisingly straightforward once you see it step by step.
Herman
Before we dive into the algorithm, let's frame the puzzle properly — because the fact that this works at all is kind of astonishing. You scan a QR code once. From that moment on, your phone and a server somewhere in a data center independently generate the same six-digit number every thirty seconds. They never speak again. No handshake, no heartbeat, no network packet.
Corn
Yet they stay synchronized for years.
Herman
The only two things they share are that secret from the QR code and an agreement about what time it is. That's it. The entire system rests on two RFCs published by a group called the Initiative for Open Authentication — OATH. They formed in two thousand four specifically to create open standards for strong authentication, because before that, every two-factor system was proprietary and incompatible.
Corn
This was an industry consortium saying, let's stop reinventing the wheel and build something everyone can use.
Herman
The first piece came out in December two thousand five — RFC four two two six, the HMAC-based One-Time Password, or HOTP. That's the core engine. Then in May twenty eleven, they published RFC six two three eight, which layers time on top of the counter-based system to create TOTP. The authors on the TOTP RFC were David M'Raihi from Verisign, Salah Machani from Diversinet, Mingliang Pei from Symantec, and Johan Rydell from Portwise. The HOTP RFC added four more names, including Mihir Bellare from UC San Diego — he's a heavyweight in cryptographic theory.
Corn
You've got industry practitioners and an academic cryptographer collaborating on an open standard. That's a pretty good pedigree.
Herman
The core insight they built on is deceptively simple. HOTP takes a counter and a secret, hashes them together, and produces a code. TOTP just replaces the counter with the current time window. The server doesn't need to ask your phone anything because it already knows both inputs — it stored the secret when you set up two-factor authentication, and it knows what time it is.
Corn
Which brings us back to Daniel's original question. How does the server know what code you're seeing? It does the same math you're doing. Same secret, same clock, same hash function. The only difference is who's holding the calculator.
Herman
Let's walk through the actual formula. It starts with TOTP equals HOTP of K and T — where K is the shared secret, and T is the time step. T is calculated as the floor of the current Unix time minus T-zero, divided by X. Default T-zero is the Unix epoch — January first nineteen seventy at midnight UTC. Default X is thirty seconds. So right now, July sixth two thousand twenty-six, Unix time is somewhere around one point seven eight billion seconds. Divide by thirty, round down — that's your time step.
Corn
Both devices are doing that same division independently. They agree on what "now" means because they agree on Unix time, and they agree on the thirty-second window. That's the synchronization.
Herman
And that time step number — call it T — gets fed into HOTP. The HOTP algorithm does three things. Step one: compute HMAC-SHA-one of the shared secret K and that counter value T. HMAC is a keyed hash construction — it takes your secret, mixes it with the counter, and produces a twenty-byte output. Twenty bytes is one hundred sixty bits of pseudorandom noise.
Corn
That's the SHA-one part everyone gets nervous about.
Herman
Which we'll get to in a second, because the concern is mostly misplaced here. Step two is the clever part — it's called dynamic truncation. You take the last byte of that twenty-byte hash, and you use its lower four bits as a number between zero and fifteen. That number tells you where to start reading a four-byte chunk from the hash. So if the last byte is, say, hex five-A, you take the lower four bits — that's ten — and you start at byte ten, pulling bytes ten through thirteen.
Corn
The offset isn't fixed — it's baked into the hash output itself. That's elegant.
Herman
It's beautiful. It means an attacker can't predict which four bytes you'll extract without computing the whole HMAC first. Then you take those four bytes, mask off the most significant bit to avoid signed versus unsigned integer confusion — so you're left with a thirty-one-bit number — and that's your raw output. Step three: take that number modulo ten to the sixth, which is one million. That gives you a number between zero and nine hundred ninety-nine thousand nine hundred ninety-nine. Pad with leading zeros to six digits, and that's your code.
Corn
Let's make this concrete. Daniel mentioned the Base32 string you see when you hit "Enter Manually." The classic example from the spec is JBSWY3DPFQQHO33SNRSCC — which, when decoded from Base32, is the ASCII string "Hello, world!" That's the actual shared secret.
Herman
So imagine that's your secret K. At a given time step — say T equals fifty-nine million and something — you feed "Hello, world!" and that counter into HMAC-SHA-one. The algorithm produces a twenty-byte hash. You look at the last byte. If it's hex zero-F, the lower four bits are fifteen, which is the maximum offset — so you'd actually wrap around using the RFC's modulo-nineteen rule, but typically you land somewhere in the middle. Let's say the offset points to bytes thirteen through sixteen. You grab those four bytes, mask the top bit, and you've got some integer. Modulo one million, pad to six digits, and that number appears on your screen.
Corn
The server, holding the same "Hello, world!" secret and computing the same time step, gets the same integer. No communication required.
Herman
Now, about SHA-one. People hear "SHA-one" and think "broken hash function," and they're not wrong — researchers demonstrated collision attacks against SHA-one years ago. But here's why TOTP doesn't care. The RFC explicitly addresses this. Section six of RFC four two two six states that "the outputs of the dynamic truncation on distinct inputs are uniformly and independently distributed strings." The HMAC construction doesn't rely on collision resistance — it relies on the pseudorandomness of the underlying compression function. And even if you could create a SHA-one collision, you'd only get the same HMAC output for two different counters, which buys an attacker nothing — they still can't reverse the hash to recover the secret, and they can't predict future outputs.
Corn
Plus you're throwing away sixteen of the twenty bytes in the truncation step. Even if someone found a theoretical weakness in the full hash output, the part you're actually using is a tiny, unpredictable slice.
Herman
The truncation step is a natural hedge. An attacker who magically broke SHA-one's collision resistance tomorrow still couldn't derive your six-digit code without the secret. The security model here is brute force — pure and simple — and the RFC gives us the exact probability. The chance of a successful guess is s times v divided by ten to the d, where s is the look-ahead window size, v is the number of verification attempts, and d is the number of digits.
Corn
With a look-ahead window of two time steps and a single guess, you're looking at two in a million. And the server should be throttling you after a handful of failures.
Herman
Which brings us to that look-ahead window. RFC six two three eight section six recommends accepting one to two time steps backward. That's why a code generated at the very start of a thirty-second window often still works fifty-nine seconds later — the server is checking the current window and the previous one. But the RFC also warns: "the longer a prover has not sent an OTP to a validation system, the longer — potentially — the accumulated clock drift." If your phone hasn't authenticated to a particular service in weeks and its clock has drifted by ninety seconds, you're three windows off. The look-ahead window can't save you.
Corn
The drift problem is worse than people think. If your phone's NTP sync silently fails — which happens more often than anyone admits, especially on cellular networks that don't prioritize time accuracy — you don't get a warning. Your codes just stop working. And the diagnostic is circular: you can't log in to check if the service is down, because you can't log in.
Herman
It's every account at once. That's the brutal part. Your TOTP codes are all generated from the same device clock. If your phone drifts two minutes off, every single service rejects you simultaneously. There's no per-account drift — the clock is global.
Corn
Which is why the "Enter Manually" button is both a convenience and a liability. When you tap that, you see the raw Base32 secret. The string that, if someone steals it, lets them generate valid codes forever — not just for thirty seconds, but indefinitely, until you rotate the secret.
Herman
The QR code is just a visual encoding of the otpauth URI. The secret itself is the crown jewel. And here's the architectural problem that most people miss: TOTP is a shared-secret system. Both your phone and the server hold the same key. If an attacker breaches the server's database — and we've seen credential database breaches at major services repeatedly — they walk away with every user's TOTP secret. From that moment, they can generate valid codes at will. No phishing required, no real-time interception.
Corn
Compare that to WebAuthn, where your device holds a private key and the server only has a public key. Stealing the server's database gives an attacker exactly nothing they can use to authenticate.
Herman
It's the difference between symmetric and asymmetric cryptography. TOTP uses a symmetric key — one secret, two locations. WebAuthn uses an asymmetric key pair — the private key never leaves your device. The shared-secret model was the right tradeoff in two thousand eleven, when TOTP was standardized, because asymmetric crypto on consumer hardware wasn't ubiquitous. Now it is, which is why the industry is shifting.
Corn
TOTP is secure against network attacks — nobody can intercept your code and replay it, because it's expired in thirty seconds — but it's vulnerable to server-side breaches in a way that passkeys simply aren't.
Herman
That thirty-second window is itself a tradeoff. The RFC's authors knew this. A code generated at the start of a window is valid for up to fifty-nine seconds — the full thirty seconds of the current window plus the look-ahead tolerance. Shorter windows would reduce that exposure, but they'd also increase clock-sync failures. The RFC settles on "at most one time step is allowed as the network delay" — meaning the server checks the current window and the previous one. Two steps, sixty seconds of validity.
Corn
Which makes the brute force math tight but not perfect. The probability formula from the RFC — s times v divided by ten to the d — gives you two in a million per guess with standard parameters. That's why throttling matters. RFC four two two six explicitly recommends locking accounts after a threshold of failed attempts, or imposing progressive delays. Without throttling, an attacker who can fire requests rapidly could eventually brute force a six-digit code — two in a million per attempt adds up over millions of attempts.
Herman
There's one more ticking clock buried in the spec that almost nobody talks about. RFC six two three eight explicitly requires that implementations "MUST support a time value T larger than a thirty-two-bit integer when it is beyond the year twenty thirty-eight." That's the Unix time overflow — January nineteenth, twenty thirty-eight, when the thirty-two-bit signed integer that represents Unix seconds rolls over to negative two billion. Any legacy TOTP system still using thirty-two-bit time will silently fail that day.
Corn
Which means somewhere, in some embedded system or ancient server rack, there's a TOTP implementation that will simply stop working in twelve years. And the people maintaining it probably don't know.
Herman
The RFC authors saw it coming in twenty eleven and put the warning right in the spec. Whether every implementer read that paragraph is a different question.
Corn
The whole elegant system — the synchronized clocks, the deterministic hashing, the dynamic truncation — it all rests on three fragile assumptions. That your device's clock is accurate. That the server's secret database hasn't been breached. And that the integer storing Unix time hasn't overflowed. Two of those three are invisible to the user until the moment they fail.
Herman
What do you actually do with all this? Three things, and they're simple enough that most people skip them.
Corn
First one's almost too obvious. Enable automatic time sync on your phone. The majority of TOTP failures trace back to clock drift, and the fix is usually toggling the "set time automatically" setting off and back on. If your codes suddenly stop working everywhere, check your device clock before you assume the service is down.
Herman
That's the diagnostic most people run in reverse. They try a different network, they reboot, they reinstall the app — meanwhile their phone is forty-five seconds off and every TOTP computation is silently wrong.
Corn
Second: treat your TOTP secrets like passwords. That "Enter Manually" button reveals the raw Base32 string. If your password manager gets compromised, that string lets an attacker generate valid codes indefinitely — not just for thirty seconds. You need to rotate every two-factor secret immediately.
Herman
The shared secret doesn't expire. A stolen password you can change. A stolen TOTP secret you have to revoke and reissue, and most people don't realize they need to do both. They change the password and think they're safe.
Corn
Third, and this is the one that makes security people nod and everyone else uncomfortable. For high-value accounts — email, banking, anything with financial or identity implications — move to WebAuthn or passkeys if the service supports it. Those eliminate the shared secret problem entirely. The server never holds anything an attacker can steal to impersonate you.
Herman
TOTP is better than SMS, dramatically better. But it's not the endgame. It's a symmetric system in a world that's moving asymmetric. Every TOTP secret stored on a server is a single point of failure waiting for a breach.
Corn
The broader point Daniel's question gets at — the thing worth sitting with — is that the elegance of TOTP is also its vulnerability. It solves a hard synchronization problem without any network communication. Two devices, one shared secret, one clock. But that same design means you're trusting three things every thirty seconds: that your device clock is accurate, that the server's clock is accurate, and that the secret database hasn't been breached.
Herman
Any one of those fails, and the math stops working. No error message explains why. The code just doesn't match, and you're locked out.
Corn
Which brings us to the question Daniel's prompt implicitly raises but doesn't quite ask. Where does this technology go from here? TOTP is deployed across millions of services, it's the fallback when passkeys aren't supported, and yet its shared-secret architecture is fundamentally the wrong shape for where authentication is heading.
Herman
I think about this as a stepping stone that's going to be with us for a very long time. WebAuthn is objectively better — asymmetric keys, no shared secret to steal, phishing-resistant by design. But TOTP has fifteen years of deployment inertia. Every bank, every email provider, every SaaS platform has it baked in. Replacing that isn't a technology problem, it's a coordination problem.
Corn
The year twenty thirty-eight issue adds a hard deadline nobody's planning for. The RFC explicitly requires sixty-four-bit time support, but somewhere out there is a thirty-two-bit embedded system running a TOTP implementation that will silently roll over to negative two billion on January nineteenth. The people who set it up might be retired by then.
Herman
Or the company might not exist anymore. And the failure mode is brutal — the math keeps running, the codes keep generating, they just don't match. No crash, no error log, just locked-out users who can't figure out why.
Corn
The thing Daniel's watching every thirty seconds — that little six-digit refresh — is simultaneously one of the most elegant pieces of cryptographic engineering ever deployed at scale, and a system with an expiration date baked into its assumptions. Synchronized clocks, a shared secret, and a hash function. That's the whole thing.
Herman
Two devices that never speak to each other, computing the same number in total silence, held together by nothing but an agreement about what time it is. Next time you tap that code, that's what you're witnessing.
Corn
Now: Hilbert's daily fun fact.

Hilbert: In the late sixteen hundreds, the Yámana people of Tierra del Fuego developed a system of over forty distinct hand gestures used exclusively by women during periods of ritual silence — essentially a full sign-language dialect that converted to about three words per second, roughly the speaking rate of modern conversational English.
Corn
...three words per second in Tierra del Fuego.
Corn
This has been My Weird Prompts. Thanks to our producer Hilbert Flumingtop. If you enjoyed this, leave us a review wherever you listen — it helps other people find the show. We'll be back soon with another one.

This episode was generated with AI assistance. Hosts Herman and Corn are AI personalities.