Skip to content

TOTP, explained without the crypto jargon

By TOTP Authenticator team ·

A TOTP code is a short number, usually six digits, that changes on a timer. It’s generated from a secret that your authenticator app and the service agreed on once, back when you first scanned a QR code or typed in a setup key. Both sides run the same calculation against the current time and land on the same digits independently. That’s the whole trick: no network round-trip, no message passed back and forth at the moment you log in, just two parties doing identical math on a shared secret and the clock.

TOTP stands for Time-based One-Time Password. It’s defined by an open standard, RFC 6238, that any app or service can implement, so it isn’t proprietary to any one company. Here’s what’s happening under the hood, without assuming you know any cryptography.

The one moment that matters: setup

When you add an account by scanning a QR code, that QR code isn’t a picture of your login. It encodes a secret, a randomly generated string, along with the account name and a couple of settings. The service generated that secret on its end and is showing it to you exactly once, in that QR code (or as a manual entry key, for services that don’t offer scanning). You store it; they store it. From that point on, neither side needs to send it anywhere again.

This is why TOTP codes work without an internet connection: the secret already lives on your device, and generating a code doesn’t require asking anyone anything.

Turning a secret and a timestamp into six digits

This is the part that sounds complicated and isn’t, once you strip the notation away. The app takes two inputs, the secret and the current time rounded down to a fixed interval (30 seconds, by default), and runs them through a one-way scrambling function called HMAC. One-way is the important property: you can compute an output from the secret, but you can’t run the process backwards to recover the secret from the output. That’s what makes it safe to display the six digits on your screen, because those digits don’t leak the thing that generated them.

The scrambling function produces a much longer string of bits than you need, so the algorithm takes a small, well-defined slice of it and turns that into a 6-digit number. That’s your code. Thirty seconds later the time input has moved to the next interval, the scramble comes out completely different, and you get a new code with no relationship to the previous one that anyone could use to predict it.

The service has the same secret stored from setup, and it knows the current time too, so it runs the identical calculation and checks whether its answer matches what you typed in. If it matches, you’ve proven you have the secret, and the secret itself never had to be sent anywhere.

Why it works offline, and what a wrong clock does

Generating a code needs only the secret (already on your device) and the current time (which every phone tracks itself), so no step in the process requires a network connection. That’s why TOTP codes work in airplane mode, in a basement with no signal, or on a phone with no SIM at all. The generation logic never reaches out to anyone.

The flip side is that both sides need to agree on roughly what time it is. The calculation rounds time into 30-second windows, and both sides have to land in the same window, or in an adjacent one, since most services accept the window before and after to allow for small drift. If your phone’s clock is meaningfully wrong, a few minutes off from a stuck sync or a manually set clock, your codes land in windows the service isn’t checking, and every code looks wrong even though nothing about your account or the app is broken. This is a common cause of “my codes stopped working” reports, and it’s why the app checks for drift and can correct it automatically instead of leaving you to diagnose a clock problem from a login failure.

Six digits and thirty seconds is a convention, not a rule

Most services you’ll come across use six digits refreshed every thirty seconds, because that’s the default the standard suggests and what most authenticator apps and services settled on. The standard itself doesn’t mandate either number. It defines the calculation and leaves digit count and interval length as parameters each service can choose. That’s why a well-built authenticator app has to read those settings out of the setup QR code, or let you enter them manually, rather than hard-coding six digits and thirty seconds everywhere; a service that chose different values would otherwise never work correctly. In practice almost every setup you’ll ever add uses the defaults, but the flexibility is part of the standard, not an extra that some apps happen to support.

What the “shared secret” model does and doesn’t protect against

Being precise about this matters. The design means nobody can generate your codes without the secret: not us, not the service, not anyone intercepting network traffic, since the secret itself is never transmitted after setup. What it doesn’t do is make the secret impossible to lose. If the only device holding a copy is lost, stolen, or wiped, the secret goes with it, which is a much more mundane problem than the one cryptography solves. That’s a question of backup and device management rather than of the math, and it’s covered in what actually happens when you lose your phone.

The short version

Setup shares a secret once. Every code after that is the secret plus the current time, scrambled one-way into six digits, computed independently by your device and the service. No network is needed to generate a code. An accurate clock is the one thing both sides quietly depend on.