Base64 解决的问题
计算机把一切都存储为字节,即 0 到 255 之间的任意值。然而,许多搬运数据的系统是为承载文本而非任意字节而构建的:电子邮件正文、URL、JSON 字符串、HTTP 头。递给它们一个恰好是控制字符或引号的原始字节,它们便会将其破坏或崩溃。Base64 是一种标准做法,把任意字节用一小套安全的可打印字符重新书写,使那些纯文本通道能原封不动地承载它们。
值得精确说明这意味着什么:Base64 是一种编码,而非加密。它不隐藏任何东西。任何人都能无需密钥、毫不费力地把它解码回原始字节。它唯一的工作是熬过传输,而非保守秘密。
编码如何工作
诀窍在于重新分组比特。Base64 每次读取三个字节的输入。三个字节是 24 比特,而 24 恰好均分为四组各 6 比特。每个 6 比特的组是一个 0 到 63 的数字,而这 64 个值中的每一个都映射到 Base64 字母表中的一个字符:
A到Z对应值 0 到 25a到z对应值 26 到 510到9对应值 52 到 61+和/对应值 62 和 63
因此每三个输入字节恰好变成四个输出字符。这就是为何 Base64 输出总比输入大约大三分之一:四个字符承载了三个字节所承载的内容。
为何存在填充
输入并不总是三字节的整数倍。当最后一组只剩一个或两个字节时,编码器仍会发出一个完整的四字符块,并用字符 = 填补空缺:
- 一个剩余字节(8 比特)产生两个有意义的字符,然后是
==。 - 两个剩余字节(16 比特)产生三个有意义的字符,然后是
=。
= 不是数据。它是一个标记,告诉解码器最后一块真正代表多少字节,使其能丢弃填充并重建确切的原始长度。这就是为何一个 Base64 字符串的长度总是四的倍数。
URL 安全变体
标准字母表中的两个字符在特定场合会带来麻烦。+ 和 / 在 URL 中都有保留含义(一个空格和一个路径分隔符),而 / 在许多文件名中也是非法的。Base64URL(在 RFC 4648 中定义)以两处替换和一个习惯来修正此问题:
+变为-/变为_- 由于长度可以推断,
=填充通常被去掉
结果是一个无需进一步转义即可干净地放入 URL、文件名或 JSON Web Token 的字符串。这正是为何 和 的 挑战使用 Base64URL 而非经典形式:那些值就生活在 URL 和令牌之中。
你在哪里遇到它
一旦你认出这个模式,Base64 无处不在:把图像直接嵌入页面的 data: URI、一个 JWT 的三个以点分隔的段、 电子邮件附件、HTTP Basic 认证头,以及 格式的证书。在每种情形里原因都相同,原始字节需要穿过一个只信任文本的通道。
你可以把文本或 Base64 粘贴进 Base64 工具,以双向对其编码或解码,标准的和 URL 安全的,全部在你的浏览器中。