第 2 课

Base64 编码原理

比特分组、六位一组与 64 字符字母表。

Base64 的核心思想很常见:比特串2 的幂、再加上一张 索引表(字母表)。没有词典、不做压缩——只是把比特按固定规则重排后用可打印字符表示。

从字节到位流

一个字节八个比特;三个字节共有 24 个比特,按先后顺序拼接成一个连续位串:

字节1:########
字节2:########
字节3:########   → 顺序连接成 24 bit

Base64把这 24 个比特划分为 四个“六位组”(sextets)

[######][######][######][######]
  ↑        ↑        ↑        ↑
 第1组    第2组    第3组    第4组

每个六位数的取值范围是 0–63,用来索引 64 个符号。这就是名称里 base 64 的含义:像在写 64 进制,只是把“数字符号”换成了可打印 ASCII。

常见标准字母表(RFC 一脉)

最常见映射为:

0–25  → A–Z
26–51 → a–z
52–61 → 0–9
62 → '+'
63 → '/'

解码则逆过来:符号 → 六个比特 → 再拼回原始的八位字节。

徒手走一遍两个小例子(感受一下填充为何会冒头)

日常工作不必手写,但能强化直觉。取 ASCII "Hi"

  • H = 0x4801001000
  • i = 0x6901101001

拼接得到 16 个比特:0100100001101001

为了在逻辑上对齐到六位一组,编码器会在 右侧0 补齐,直到长度为 6 的倍数——具体如何表现为输出里的字符与 =,下一课展开:

010010 | 000110 | 100100 |
  18      6       36

若输入在此时结束,第 4 个六位组需要借助 填充规则补齐;解码器会根据 = 知道哪些六位组是“补出来的”。库会替你处理这些——理解分组后你就能明白 为什么编码后更长,以及为什么在传输错误时解码结果会像“整块错位”。

为什么编码后体积大约多出三分之一

三组字节(24 比特)会变成 四个编码字符——同样的信息量被摊开成可打印形态。粗略来说:若输入有 n 个字节,编码后大约 ceil(4n/3) 个字符(不计填充);若 n % 3 ≠ 0,末尾还会出现 =。体积换 兼容性,这是刻意的取舍。

解码的对称性

解码步骤:

  1. 按同一种字母表,把字符映射回 0–63(若混用 URL-safe 变体,须与编码端一致)。
  2. 将所有六位值拼成一个连续比特串。
  3. 从左到右按 8 比特切回字节。

若字符串里有非法符号、混入不可见空白、或选了错误的字母表,= 个数不对——解析就会失败;部分宽松实现在边界处还可能产生 不一致的行为,这是为什么生产代码应坚持严格校验。

要点小结

Base64 把输入比特 按六位重切分,并为每组选取 64 个约定字符中的一个。头脑中有了“六位一组”这张图,后续的 填充URL-safe 替换就只是在这个模型上的两个小补丁。

想动手练习时,可使用 DevCove 相关工具——可选,不属于本课正文。

打开相关工具

返回课程概览