上传文件
  1. base64hub
  2. Base64 字母表(编码对照表)

Base64 字母表(编码对照表)

Base64 把 0 到 63 之间的每个 6 位数值映射成一个可打印字符。下面是完整的对照表、URL 安全版本,以及哪些字符会出现在哪些位置的规律。

64 个字符

Base64 每次读取 3 个字节(24 位)的输入,把它们拆成四个 6 位的数。每个数的范围是 0 到 63,用作这张表的索引。顺序由 RFC 4648 规定:0 到 25 是大写字母,26 到 51 是小写字母,52 到 61 是数字,然后是 + 和 /。最后一列是该字符的 ASCII 码,也就是实际存储或传输的内容。

索引6 位Base64Base64URLASCII 码
0000000AA0x41
1000001BB0x42
2000010CC0x43
3000011DD0x44
4000100EE0x45
5000101FF0x46
6000110GG0x47
7000111HH0x48
8001000II0x49
9001001JJ0x4A
10001010KK0x4B
11001011LL0x4C
12001100MM0x4D
13001101NN0x4E
14001110OO0x4F
15001111PP0x50
16010000QQ0x51
17010001RR0x52
18010010SS0x53
19010011TT0x54
20010100UU0x55
21010101VV0x56
22010110WW0x57
23010111XX0x58
24011000YY0x59
25011001ZZ0x5A
26011010aa0x61
27011011bb0x62
28011100cc0x63
29011101dd0x64
30011110ee0x65
31011111ff0x66
32100000gg0x67
33100001hh0x68
34100010ii0x69
35100011jj0x6A
36100100kk0x6B
37100101ll0x6C
38100110mm0x6D
39100111nn0x6E
40101000oo0x6F
41101001pp0x70
42101010qq0x71
43101011rr0x72
44101100ss0x73
45101101tt0x74
46101110uu0x75
47101111vv0x76
48110000ww0x77
49110001xx0x78
50110010yy0x79
51110011zz0x7A
52110100000x30
53110101110x31
54110110220x32
55110111330x33
56111000440x34
57111001550x35
58111010660x36
59111011770x37
60111100880x38
61111101990x39
62111110+-0x2B
63111111/_0x2F
填充–=通常省略0x3D

有两个区间值得记住。从 A 到 P(0 到 15)的每个字符都以比特 00 开头,从 w 到 /(48 到 63)的每个字符都以 11 开头。手工检查前缀时,靠这两条就能在脑子里解出一个字符。比特拆分的完整示例见 Base64 的工作原理。

字母表的顺序不是 ASCII 顺序。在 ASCII 中,+ 和 / 排在最前,然后是数字、大写字母、小写字母。因此对 Base64 字符串排序,并不等于对底层字节排序:+A==(字节 F8)会排在 AA==(字节 00)前面。如果需要编码后的值与原始字节排序一致,请使用 RFC 4648 中的 base32hex 或直接用 hex。

URL 安全字母表

+ 和 / 在 URL 中都有特殊含义。在查询字符串和表单数据里,+ 会被解码成空格,而 / 用来分隔路径段。RFC 4648 第 5 节定义的 Base64URL 保留索引 0 到 61 不变,只替换最后两个:

索引Base64Base64URL
62+-
63/_

其余部分(包括比特布局)完全相同,所以两者互转只需替换字符,再补上或去掉填充。JWT、许多 API 令牌以及可安全用作文件名的标识符都使用 Base64URL,而且通常不带 =。Base64URL 编码器 可以直接生成这种格式。完整对比见 Base64 与 Base64URL 的区别。

填充符

=(ASCII 0x3D)不属于这 64 个字符,也从不编码数据。只有当输入长度不是 3 的倍数时,它才用来填满最后一个 4 字符组:

  • 剩 1 个字节:2 个数据字符加 ==。
  • 剩 2 个字节:3 个数据字符加 =。
  • 没有剩余字节:不填充。

所以带填充的字符串长度总是 4 的倍数,你也永远不会看到 ===。不带填充时,长度除以 4 的余数是 0、2 或 3,绝不会是 1。何时可以省略 =、如何把它补回来,见 填充指南。

哪些字符出现在哪些位置

有几条规律直接来自比特布局。它们都经过对所有相关字节值的穷举验证。

== 前面只会出现 A、Q、g 或 w。剩 1 个字节时,第二个字符包含 2 个数据位,后面跟 4 个零位,所以它的索引只能是 0、16、32 或 48。单个 = 前面的第三个字符末尾有 2 个零位,因此只能是这 16 个字符之一:A E I M Q U Y c g k o s w 0 4 8。这个位置出现其他字符,说明编码不规范,严格的解码器会拒绝它。

随机字节会均匀地用到全部 64 个字符。随机数据的每个 6 位组都是均匀分布的,所以加密数据、密钥和压缩文件的字符分布是平的。分布明显不均,说明数据是文本或者有某种结构。

ASCII 文本的组首字符不会是小写 g 到 z、数字、+ 或 /。每个 4 字符组的第一个字符承载某个字节的高 6 位。7 位 ASCII 的最高位是 0,所以这个字符总在 A 到 f 之间(索引 0 到 31)。在 SGVsbG8gd29ybGQh(Hello world!)中,各组的首字符分别是 S、b、d 和 b。

ASCII 文本的 Base64 里很少有 + 和 /。对于小于 0x80 的字节,+ 只能作为某组的第四个字符出现,且第三个字节是 > 或 ~。/ 只有在该字节是 ? 或 DEL 控制字符时才会出现在那里。这就是 Hi?> 编码为 SGk/Pg==、<b> 编码为 PGI+ 的原因。

连续的 A 是零字节,连续的 / 是 0xFF。AAAA 是三个 00 字节,//// 是三个 FF 字节。大段的 A 常见于稀疏的二进制格式、UTF-16 文本(Hello 是 SABlAGwAbABvAA==)以及 SSH 密钥开头的长度字段。更多可辨认的模式见 常见的 Base64 前缀。

其他 Base64 字母表

有几个系统沿用了“每 6 位对应 64 个字符之一”的思路,但选用了不同的字符:

变体按索引顺序排列的字母表使用场景
标准A-Z a-z 0-9 + /RFC 4648、MIME、PEM、大多数 API
URL 安全A-Z a-z 0-9 - _RFC 4648 第 5 节、JWT
IMAP 邮箱名A-Z a-z 0-9 + ,RFC 3501 修改版 UTF-7
bcrypt. / A-Z a-z 0-9$2a$、$2b$、$2y$ 密码哈希
crypt(3). / 0-9 A-Z a-zMD5-crypt $1$、SHA-crypt $5$ 和 $6$、DES crypt
xxencode+ - 0-9 A-Z a-z早期 Unix 邮件和 Usenet
uuencodeASCII 32 到 95(空格到 _),0 常用 ` 表示早期 Unix 邮件和 Usenet
  • IMAP 把 / 换成了 ,,因为 / 是邮箱名中常用的层级分隔符。名为 Entwürfe 的文件夹会存储为 Entw&APw-rfe。
  • bcrypt 把 . 和 / 移到最前面,并让字母排在数字前面。它的盐值和哈希都是用这个字母表、不带填充的 Base64,所以用标准解码器解出来的字节是错的。
  • crypt(3) 使用 ./0-9A-Za-z,这正好是 ASCII 顺序。它还从最低有效位开始打包比特,所以即使换算了字母表,标准解码器也还原不出哈希字节。
  • uuencode 和 xxencode 比 MIME 还早。uuencode 和 xxencode 工具都能读写这两种格式。

对于字母表大小不同的编码,例如 Base32、Base58 和 Base85,请参阅 Base64 与 hex、Base32、Base58、Base85 的对比。本文用到的术语定义见 术语表。

常见问题

Base64 字母表一共有多少个字符?

用于承载数据的有 64 个:26 个大写字母、26 个小写字母、10 个数字,加上 + 和 /。填充符 = 是第 65 个符号,它从不承载数据。

字母 A 在 Base64 中对应的值是多少?

A 代表索引 0,二进制为 000000。B 是 1,Z 是 25,a 是 26,z 是 51,0 是 52,9 是 61,+ 是 62,/ 是 63。

Base64URL 改了哪些字符?

只改了两个:+(索引 62)变成 -,/(索引 63)变成 _。通常还会去掉填充。可以用 Base64 转 Base64URL 转换。