把字节写成文本的四种方式
Base16(hex)、Base32、Base64 和百分号编码都解决一个问题:用纯文本通道能安全传输的字符来表示数据。它们在两个相互权衡的轴上有所不同,字母表大小和体积开销。更大的字母表每个字符打包更多位,所以输出更短;更小或更受限的字母表更易读或在给定情境中更安全,但输出更长。前三种在 RFC 4648 中一起定义;百分号编码来自 RFC 3986,工作方式与其余的不同。
一眼看懂体积开销
对于原始二进制输入,RFC 4648 三种编码的膨胀是固定且可预测的:
编码 位/字符 比率 开销
Base16 4 2 字符 / 字节 +100%
Base32 5 8 字符 / 5 字节 +60%
Base64 6 4 字符 / 3 字节 +33%
Base64 最紧凑,Base16 最不。百分号编码是个例外:它根本不是固定比率。它让非保留字符保持不动,只把其余的每个扩展为三个字符,所以它的开销完全取决于内容。对于主要是字母和数字的文本,它几乎是免费的;对于原始二进制,几乎每个字节都需要转义,它飙升到约 +200%,比其他任何一种都差。
字母表与可读性
- Base16 / hex 使用
0-9和A-F。一个字节始终是两个字符,所以字节边界完全清晰。它最易于用眼睛读取和比较,这就是为什么哈希、密钥和十六进制转储都用它。 - Base32 使用
A-Z和2-7,大小写不敏感,去掉了易混淆的字符0、1和8。它是为人会输入、口述或在不区分大小写的情况下存储的值而设计的,比如 密钥和 onion 地址。 - Base64 使用
A-Z、a-z、0-9、+和/,大小写敏感。它是三者中最密的,但+和/在 URL 和文件名中不安全,而 URL 安全变体修复了这一点。 - 百分号编码让可读文本保持可读,只转义 URL 无法按字面传输的部分。它是一种转义方案,而非完整的重新编码。
该选哪一个
选择取决于通道和受众。如果人必须读取、输入或比较该值,优先选 hex(用于检查字节)或 Base32(用于输入或口述)。如果机器必须通过文本通道搬运任意字节且大小重要,使用 Base64,或当值在 URL、文件名或令牌内传输时使用 Base64URL。如果你在把文本放入 URL 而只有少数字符不安全,就对它进行百分号编码,而不是重新编码一切。
一条快速规则:紧凑用 Base64,输入用 Base32,读取用 hex,URL 用百分号编码。
试试它们
codec 工具运行全部四种。粘贴任意文本,切换编码,并排比较输出,每种都有解码,全部在你的浏览器中完成。