为何TOTP实现普遍采用Base32而非Base64?相关RFC规范疑问
Great question—even though TOTP secrets aren’t front-and-center for users day-to-day, there are practical, user-centric reasons Base32 became the de facto standard over Base64:
- No confusing characters: Base32 uses a restricted set of alphanumerics (A-Z, 2-7) that eliminates easily mixed-up pairs like
0vsO,1vsIvsl. This is critical for scenarios where users might need to manually enter a secret (e.g., if scanning a QR code fails). Base64 includes+,/, and padding characters like=, which are not only harder to type but can cause issues in contexts like URL parameters or form inputs (where special characters often need escaping). - Case insensitivity: Most TOTP implementations treat Base32 secrets as case-insensitive, cutting down on user error when typing. Base64 is typically case-sensitive, adding another layer of potential mistakes.
- Negligible storage overhead: While Base32 is ~20% less space-efficient than Base64, TOTP secrets are tiny (usually 16-32 bytes). For a 16-byte secret, Base32 encodes to 26 characters vs Base64’s 22—hardly a meaningful difference in modern systems. The tradeoff for better usability is well worth it.
You’re absolutely right—neither RFC 6238 (TOTP) nor RFC 4226 (HOTP) explicitly mention Base32. Here’s the context behind that:
These RFCs define the core cryptographic algorithm, focusing solely on how to generate one-time passwords from a secret key (raw octet string) and a counter/timestamp. They don’t dictate how the secret should be encoded for transmission or user input—that’s left as an implementation detail for cross-app interoperability.
Early TOTP tools (like Google Authenticator) adopted Base32 for encoding secrets, and this choice quickly became a de facto standard to ensure apps could work with each other. So when tools like FreeOTP say they follow the RFCs, they mean the underlying TOTP/HOTP logic aligns with the specs—using Base32 is just the widely accepted way to handle the secret’s human-readable form, not a requirement from the RFCs themselves.
内容的提问来源于stack exchange,提问作者Leth

