What Is Base32 Encoding and How Is It Used in Two-Factor Auth?

Base32 encoding — Chunky Munster

Base32 encoding is a text-safe way to represent binary data using a limited alphabet, which is why it shows up in two-factor authentication setup keys. If you’ve ever copied a long secret into an authenticator app, you’ve already dealt with it indirectly. To test the format yourself, give the Base32 encoder-decoder a spin.

What Base32 encoding actually does

Base32 takes raw bytes and converts them into a string made from 32 symbols, usually uppercase letters and digits. The point is not compression and not secrecy. It is readability and transport: fewer ambiguous characters, lower risk of copy-paste damage, and better compatibility with systems that only want plain text.

The usual alphabet is designed to avoid the usual human mistakes. You will often see uppercase letters and digits like 2 through 7, while characters that are easy to confuse, such as 0, 1, I, and O, are kept out of the standard set. Padding with = may appear at the end to make the output length line up neatly.

That means Base32 is an encoding, not an encryption method. Anyone with the encoded text can decode it back into the original bytes. If you need confidentiality, you need encryption on top of encoding, not encoding alone.

Why authenticator apps use it

Two-factor authentication systems need a shared secret between your server and the authenticator app. That secret is usually binary data under the hood, but a QR code or backup setup screen needs text, not raw bytes. Base32 is a practical bridge between those two worlds.

When you scan a QR code in an app like Google Authenticator, 1Password, or Authy, the QR payload usually contains an otpauth:// URI. Inside that URI, the secret is typically Base32-encoded so the app can copy it reliably into its TOTP algorithm.

In TOTP setups, Base32 is not the security layer. It is the packaging that gets the shared secret from your server into the app without mangling it.

This also helps with manual entry. If a user cannot scan the QR code, they can type the secret by hand. A restricted alphabet keeps support tickets down, because the difference between a working code and a dead one is often a single mistyped character.

If you want a broader primer on binary-to-text formats, our guide on why Base64 is everywhere and what it actually does is a useful comparison point. Base64 is more compact, but Base32 is often more human-friendly in auth flows.

Base32 vs Base64 vs hex

These three formats solve similar problems, but they trade off readability, size, and compatibility differently. Hex is the simplest to eyeball because it uses only 0-9 and a-f, but it doubles the size of the data. Base64 is more compact than hex, but it uses symbols like +, /, and sometimes =, which can be awkward in URLs, config files, or manual transcription.

Base32 sits in the middle. It is less compact than Base64, but it is easier to read out loud, type by hand, and print on a recovery card without creating a mess. That is why it shows up in places where humans still matter.

There is no universal winner. The right choice depends on whether your main threat is bandwidth, line length, or human error. In 2FA, human error is usually the one that bites first.

How the encoding works under the hood

Base32 processes the input in 5-bit chunks. That matters because 32 possible symbols can represent exactly 5 bits each, since 2^5 = 32. The encoder reads binary data, groups the bits, and maps each group to a character in the Base32 alphabet.

Because real data rarely lands on a perfect boundary, padding may be added. That padding tells the decoder how many bits were part of the final chunk. Different implementations can be a little picky about padding rules, casing, or whether they accept whitespace, so it is worth using a standard-compliant encoder/decoder when you are generating secrets.

In code, the logic is boring in a good way. A common pseudo-flow looks like this:

bytes -> bit stream -> 5-bit groups -> Base32 alphabet characters -> optional padding

Decoding simply reverses the process. Each character maps back to a 5-bit value, the bits are concatenated, and the original bytes are reconstructed. If a character is outside the alphabet, the decoder should reject it instead of guessing.

Where mistakes happen

The most common Base32 problems are not mathematical. They are operational. Someone copies the secret with a trailing space, drops a character, confuses a letter with a number, or pastes an uppercase/lowercase mix into a system that expects canonical uppercase.

Another classic failure mode is using the wrong alphabet. Base32 has variants, and not all of them are interchangeable. The version used for TOTP secrets is usually the RFC 4648 alphabet, not some custom encoding that only works inside one toolchain.

Watch for these issues when you handle secrets:

  1. Do not trim characters unless you know the tool inserted accidental whitespace.
  2. Do not invent substitutions for missing characters.
  3. Do not assume every Base32 string is valid for TOTP.
  4. Do not treat the encoded secret as protected data; store it as carefully as the original secret.

At the workflow level, this is the same kind of boring-but-important cleanup you do when you strip duplicates or normalize text before processing it. The data only works if every character survives the trip intact.

A Worked Example

Here is a simple example using a short ASCII string. This is not a real 2FA secret, but it shows the transformation clearly.

Input text:  hello

When encoded in Base32, the output becomes:

NBSWY3DP

That output is short, uppercase, and safe to copy into systems that dislike punctuation. If you add padding in a stricter implementation, you may see something like:

NBSWY3DP

Now imagine a real TOTP secret. The human-facing version might look like this:

JBSWY3DPEHPK3PXP

That string gets embedded into a QR payload or typed into an authenticator app. The app decodes it back to bytes, then uses those bytes as the shared secret when it generates one-time passwords.

Here is the rough shape of an otpauth:// URI that an app might read:

otpauth://totp/Acme:dev@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Acme

The important part is the secret parameter. The rest is metadata for display and organization. If the secret is malformed, the app and server will derive different codes, and login will fail every 30 seconds until someone fixes it.

When Base32 is the right choice

Base32 is a sensible default when you need a text representation that humans may touch. That includes backup codes, manual 2FA enrollment, offline recovery sheets, and QR payloads that need to be copied into a config system later.

It is also useful in debugging and interoperability. If you are inspecting an auth setup and want to confirm that the server and client are using the same shared secret, being able to read the string directly helps. You do not need to guess what a blob of binary means.

Pick Base32 when the cost of a mistaken character is higher than the cost of extra length. Pick Base64 when compactness matters more and human transcription does not. Pick hex when you want maximum transparency and do not mind the bloat.

For most developers, that decision comes down to context, not purity. Auth setup? Base32 is usually the cleanest fit. API payload? Probably Base64. Low-level debugging? Hex is still hard to beat.

Frequently Asked Questions

Is Base32 encoding secure?

No. Base32 encoding does not encrypt or hide data, so anyone who has the encoded string can decode it. For two-factor auth, the security comes from the secret value and the TOTP process, not from Base32 itself.

Why do authenticator apps use Base32 instead of Base64?

Base32 is friendlier for manual entry because it avoids many confusing characters and uses a limited uppercase alphabet. That makes it less painful when a user has to type a secret from a paper backup or a setup screen. Base64 is more compact, but not as friendly for humans.

Can I decode a Base32 secret into plain text?

Yes, if the original bytes were just text, you can decode them back into readable characters. But many 2FA secrets are not meant to be human-readable text at all; they are binary keys represented as Base32. Decoding them may produce raw bytes that do not look like words.

What happens if I type one character wrong in a Base32 secret?

The server and authenticator app will derive different time-based codes, so logins will fail. Because TOTP codes change constantly, even one wrong character breaks the shared secret. If a setup fails, re-scan the QR code or re-enter the secret carefully instead of trying to guess the bad character.

Wrapping Up

Base32 encoding is a text wrapper for binary data, and in two-factor auth it exists to make shared secrets easier to move around without wrecking them. It is not encryption, not compression, and not magic. It is just a practical format that plays well with QR codes, manual entry, and backup notes.

If you are building or debugging an auth flow, check the alphabet, confirm the padding rules, and make sure both sides are using the same secret. If you just want to see how the conversion works on real input, use the Base32 encoder-decoder tool and compare the encoded text with the decoded result.

That usually clears up the mystery fast. Once you can read the format, the rest of the 2FA pipeline stops looking like arcane ritual and starts looking like a very ordinary string transformation.

// try the tool
give the Base32 encoder-decoder a spin →
// related reading
← all posts