TOTP Secret Generator

Base32 OTP secrets for authenticator apps

Generate base32-encoded TOTP secrets compatible with Google Authenticator, Authy, 1Password, and other RFC 6238 apps. Builds the otpauth URI and a scannable QR code entirely in your browser using the Web Crypto API. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What is a TOTP secret?

A TOTP secret is a shared random key, encoded in base32, that both your server and the user's authenticator app hold. Each app derives the same time-based 6-digit code from it using the RFC 6238 algorithm, so codes match without any network call.

A TOTP secret is the shared key behind every time-based one-time password. When a user enables two-factor authentication, your server generates a random secret, encodes it in base32, and shows it to the user as a QR code. Their authenticator app — Google Authenticator, Authy, 1Password, Microsoft Authenticator — stores that secret and, every 30 seconds, derives a 6-digit code from it using the RFC 6238 algorithm. Because both sides hold the same secret and use the same clock, the codes match without any messages crossing the network. This tool generates a compliant secret, the otpauth:// enrollment URI, and a scannable QR code, all locally.

How it works

The generator produces a fresh secret and packages it for an authenticator app:

  1. Draw 20 random bytes (160 bits) from crypto.getRandomValues.
  2. Encode those bytes in base32 (RFC 4648 alphabet A-Z2-7), the format every authenticator expects.
  3. Build the standard enrollment URI: otpauth://totp/Issuer:label?secret=...&issuer=...&algorithm=SHA1&digits=6&period=30.
  4. Render that URI as a QR code so the app can be enrolled with one scan.

At verification time the app and your server independently compute HOTP(secret, floor(unixTime / 30)) and truncate to 6 digits. No secret travels over the wire after enrollment.

The otpauth URI in full

The URI the generator produces follows this structure:

otpauth://totp/MyApp:[email protected]
  ?secret=JBSWY3DPEHPK3PXP
  &issuer=MyApp
  &algorithm=SHA1
  &digits=6
  &period=30

Every authenticator app parses this from the QR scan. The issuer and label fields appear in the app’s account list, so users can tell which service the code belongs to. Do not omit them — without a clear issuer, users end up with a list of unlabelled codes they cannot identify.

What to store on your server

After enrollment you need to persist the base32 secret linked to the user’s account. At verification time, recompute the code and compare. A common pattern:

  • Store the secret encrypted at rest (for example AES-256 with a KMS-managed key).
  • Allow a one-step time window on either side of the current window to tolerate clock drift — this covers period - 30 to period + 30 seconds without meaningfully weakening security.
  • Generate and show backup recovery codes at enrollment time. If the user loses their device, these single-use codes let them regain access. Store them hashed, never plaintext.

Parameter choices

ParameterDefaultNotes
AlgorithmSHA-1All apps support this; SHA-256 is theoretically stronger but not universally supported
Digits6Universal. Some apps support 8, but 6 is the standard
Period30 sStandard. 60-second periods exist but reduce security
Key length160 bits (20 bytes)Matches SHA-1 HMAC block; RFC 4226 minimum is 128 bits

Changing any of these from the default narrows your app’s compatibility. Stay with the defaults unless a specific requirement demands otherwise.

Security notes

Everything runs in your browser. No secret, issuer name, or label is transmitted anywhere. Treat the displayed secret as a live credential — anyone who captures it can generate valid codes indefinitely. Clear the page once enrollment is complete, and never log or email the raw secret.