如何把文本编码为 Base32
- 在 输入 · 文本 中输入或粘贴文本。勾选 实时 后,每按一次键输出都会更新。
- 在 输出 · Base32(RFC 4648) 中查看结果。取消勾选输出下方的 填充(=) 可以去掉末尾的
=号。 - 需要其他变体时,打开 到,选择 Base32hex、Crockford Base32 或 z-base-32。
- 要改为解码,请在方向切换中点击 Base32(RFC 4648)→ 文本。专门的 Base32 解码器默认就是这个方向。
- 用 复制输出 或 下载 带走结果。
默认情况下,文本按 UTF-8 转换为字节。如果需要同一段文本在其他编码(例如 Windows-1252 或 UTF-16LE)下的 Base32,请修改输入下方的 字符集。
Base32 的工作原理
Base32 每次读取输入的 5 个比特,每 5 个比特写出一个字符。5 个字节(40 比特)恰好变成 8 个字符,所以输出比输入大 60%。同样数据的 Base64 字符串只大 33%,这是 Base32 只使用大写字母和六个数字所付出的代价。
当输入长度不是 5 字节的倍数时,最后一组会用 = 补满 8 个字符。下面是 RFC 4648 的测试向量,由本工具生成:
| 输入 | Base32 | 不带填充 |
|---|---|---|
f | MY====== | MY |
fo | MZXQ==== | MZXQ |
foo | MZXW6=== | MZXW6 |
foob | MZXW6YQ= | MZXW6YQ |
fooba | MZXW6YTB | MZXW6YTB |
foobar | MZXW6YTBOI====== | MZXW6YTBOI |
填充不携带任何数据。解码器可以根据真实字符的个数算出字节数,所以很多格式都会去掉填充。
Base32 变体:RFC 4648、base32hex、Crockford、z-base-32
“Base32”指的是一个家族。四个成员都是每个字符 5 比特,区别在于字母表以及是否使用填充。同样五个字节 Hello 在各变体下的结果:
| 变体 | 字母表 | Hello | 填充 | 常见场景 |
|---|---|---|---|---|
| RFC 4648 Base32 | A–Z、2–7 | JBSWY3DP | = | TOTP/2FA 密钥、Tor v3 洋葱地址、IPFS CIDv1(b…,小写) |
| Base32hex | 0–9、A–V | 91IMOR3F | = | DNSSEC NSEC3 记录;编码后的字符串排序与字节顺序一致 |
| Crockford Base32 | 0–9、A–Z,去掉 I L O U | 91JPRV3F | 无 | 需要人念出和输入的 ID |
| z-base-32 | ybndrfg8ejkmcpqxot1uwisza345h769 | jb1sa5dx | 无 | 面向人的密钥和标识符 |
Base32hex 和 Crockford 看起来很像,但它们是不同的字母表:从 H 之后开始出现差异,所以 91IMOR3F 和 91JPRV3F 是同样的字节。选错字母表也能解码而不报错,只是会悄悄给你不同的字节。
这里的 Crockford 解码器按 Crockford 的本意做了容错:它把 I 和 L 读作 1,把 O 读作 0,并跳过连字符,所以 91JP-RV3F 仍然得到 Hello。它不会添加或校验 Crockford 可选的校验符号。
用于 TOTP 和 2FA 密钥的 Base32
身份验证器应用从 otpauth:// 链接中获取密钥,这个链接通常以二维码的形式显示:
otpauth://totp/Example:alice@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example
secret 参数是不带填充的 RFC 4648 Base32。JBSWY3DPEHPK3PXP 有 16 个字符,所以包含 10 个字节。RFC 4226 推荐使用 160 位(20 字节)的密钥,对应 32 个 Base32 字符。如果你的密钥以 Base64 或 hex 形式存储,请用 Base64 转 Base32 转换。把 Base64 文本输入到这个页面,编码的是这些字符本身,得到的 Base32 虽然有效,字节却是错的,用它生成的每个验证码都会被拒绝。
TOTP 密钥就是一把钥匙:任何拿到它的人都能生成你的验证码。本页面在你的浏览器标签页内处理密钥,页面的内容安全策略会阻止它发起除 Cloudflare 的浏览量统计以外的网络请求。
在命令行和 Python 中使用 Base32
GNU coreutils 提供了一个用法与 base64 相同的 base32 命令:
printf 'Hello' | base32
printf 'JBSWY3DP' | base32 -d
第一行输出 JBSWY3DP,第二行输出 Hello。Python 标准库包含全部三种 RFC 4648 形式:
import base64
base64.b32encode(b"Hello") # b'JBSWY3DP'
base64.b32hexencode(b"Hello") # b'91IMOR3F'
base64.b32encode(b"Hi").decode().rstrip("=") # 'JBUQ'
更多编码写法见 Python 页面。关于解码,包括 Python 抛出的填充错误和小写错误,见 Base32 解码器。
常见问题
为什么 Base32 输出以 ====== 结尾?
Base32 以 5 字节为一块,每块变成 8 个字符。最后一块不足 5 字节时,RFC 4648 会用 = 把剩下的位置补满 8 个字符,所以 Hi 变成 JBUQ====。如果接收方只要 JBUQ,请取消勾选 填充(=)。
Base32 区分大小写吗?
RFC 4648 的字母表是大写的,但大多数解码器也接受小写,本解码器也是如此。Python 是个例外:除非传入 casefold=True,否则 base64.b32decode 会拒绝小写。
该用 Base32 还是 Base64?
如果只有程序读取数据,用 Base64:它更短(开销 33%,而 Base32 是 60%)。如果需要人来阅读、输入或念出这个值,或者它必须通过 DNS 名称、某些文件系统这类不区分大小写的系统,就用 Base32。
Base32 使用哪些字符?
RFC 4648 Base32 使用 A–Z 和 2–7,外加用于填充的 =。它不使用数字 0、1、8 和 9,所以含有这些数字的字符串要么是 base32hex 或 Crockford,要么根本不是 Base32。