Copynix
Security8 min read

What Is TOTP? A Complete Developer's Guide to Time-Based One-Time Passwords

Learn how TOTP (Time-Based One-Time Password) works under the hood — including the RFC 6238 algorithm, secret keys, time windows, and how to implement 2FA securely in your own application.

T

Nguyễn Văn Thương

Founder, Copynix

TOTP2FAauthentication

What Is TOTP?

TOTP stands for Time-Based One-Time Password. It is a widely adopted algorithm (standardized in RFC 6238) that generates short-lived numeric codes used as a second authentication factor. You've seen these codes in Google Authenticator, Authy, or Microsoft Authenticator — a six-digit number that changes every 30 seconds.

Unlike a static password that can be stolen and reused indefinitely, a TOTP code is valid for only one time window (typically 30 seconds). Even if an attacker intercepts a code, it becomes useless the moment that window expires.

How TOTP Works — The Algorithm

TOTP is built on top of HOTP (HMAC-Based One-Time Password, RFC 4226), replacing the counter variable with a time-derived counter. Here's the full computation:

  1. Shared secret — During enrollment, your app and the authentication server exchange a secret key (typically Base32-encoded, e.g., JBSWY3DPEHPK3PXP). This secret never leaves the device after setup.
  2. Time counter — The current Unix timestamp is divided by the time step (30 seconds by default): T = floor(unix_time / 30)
  3. HMAC-SHA1 — The time counter is hashed with the secret key using HMAC-SHA1: hmac = HMAC-SHA1(secret, T)
  4. Dynamic truncation — A 4-byte chunk is extracted from the HMAC output using offset-based truncation, producing a 31-bit integer.
  5. Modulo — The integer is reduced modulo 10^6 to produce a 6-digit code: code = integer % 1_000_000

Both the client (your phone app) and the server perform this same computation independently. If the resulting codes match, authentication succeeds — no network exchange of the code is required between client and server during the auth flow itself.

# Pseudocode for TOTP generation
import hmac, hashlib, struct, time, base64

def generate_totp(secret_base32: str, digits=6, step=30) -> str:
    secret = base64.b32decode(secret_base32.upper())
    counter = int(time.time()) // step
    msg = struct.pack(">Q", counter)          # 8-byte big-endian counter
    h = hmac.new(secret, msg, hashlib.sha1).digest()
    offset = h[-1] & 0x0F
    code = struct.unpack(">I", h[offset:offset+4])[0] & 0x7FFFFFFF
    return str(code % (10 ** digits)).zfill(digits)

TOTP vs HOTP: What's the Difference?

HOTP generates codes based on a counter that increments with each use. TOTP replaces that counter with the current time. This creates a key tradeoff:

TOTP is the dominant standard for authenticator apps precisely because its short validity window dramatically limits the utility of phishing attacks.

The Secret Key: Your TOTP Seed

The secret key is the foundation of TOTP security. It is typically:

The otpauth URI format encodes all enrollment parameters:

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

Scanning this as a QR code in any RFC 6238-compliant app (Google Authenticator, Authy, Bitwarden) will set up TOTP for that account.

Security Considerations for Developers

Protect the secret key at rest

The secret key is as sensitive as a password. Store it encrypted in your database (not plain text). If an attacker obtains the secret key, they can generate valid codes indefinitely. Use your application's encryption-at-rest strategy (e.g., AES-256-GCM with a key stored in a KMS).

Enforce HTTPS

TOTP codes are transmitted from the user's browser to your server during login. Always use HTTPS to prevent interception. A code intercepted over HTTP can be replayed within the 30-second window.

Rate limiting and code replay prevention

Implement rate limiting on TOTP submission (e.g., max 5 attempts before lockout). Track recently used codes server-side and reject reuse within the same window to prevent replay attacks.

Backup codes

Always generate a set of single-use backup codes during enrollment. Users who lose access to their authenticator app need a recovery path. Store hashed backup codes, not plain text.

Clock drift tolerance

RFC 6238 recommends accepting codes from the current window and the immediately adjacent windows (±1 step, so ±30 seconds). This accounts for slight clock differences between client and server. Don't extend this tolerance unnecessarily — a wider window gives attackers more time.

Every major language has a battle-tested TOTP library:

Use a library rather than rolling your own TOTP implementation. Cryptographic libraries handle edge cases (Base32 padding, big-endian encoding, clock skew tolerance) that are easy to get wrong.

Testing TOTP During Development

Use Copynix's TOTP generator to verify your implementation during development. Paste your test secret key and confirm the generated codes match what your server accepts. This is especially useful when testing TOTP integration before a production rollout.

Summary

TOTP is a proven, widely supported 2FA standard that dramatically improves account security without requiring internet connectivity on the authenticator side. Understanding the underlying algorithm — HMAC-SHA1, time-derived counters, and dynamic truncation — helps you implement it correctly and debug issues when they arise.

The most important implementation details: secure secret key storage, HTTPS enforcement, rate limiting, and backup code generation. Get these right and TOTP becomes a robust second factor for your users.

Free tool

Try it yourself — TOTP 2FA Generator

Runs entirely in your browser. No signup, no data sent to servers.

Open TOTP 2FA Generator
T

Nguyễn Văn Thương

Founder & Developer · Copynix

Software developer focused on web security and developer tooling. Built Copynix to provide privacy-respecting browser tools that never send your data to a server.

More about the author →

Keep Reading

All articles →
All articlesBrowse tools →