Base64 是编码,不是加密。任何人拿到 Base64 字符串,都可以把它解码回原始内容。
Hello -> SGVsbG8=它的作用是把二进制数据转换成只包含常见 ASCII 字符的文本,方便放进 JSON、HTML、CSS、配置文件或接口字段里。
编码原理:3 个字节如何变成 4 个字符?
一个字节有 8 个二进制位(bit)。Base64 每次取 3 个字节,共 24 位,再按从左到右的顺序重新分成 4 组,每组 6 位。6 位能表示 0~63 共 64 个数值,每个数值都对应字母表中的一个字符,这就是 Base64 名称中 64 的由来。
| 索引(从 0 开始) | 标准 Base64 字符 |
|---|---|
| 0~25 | A~Z |
| 26~51 | a~z |
| 52~61 | 0~9 |
| 62 | + |
| 63 | / |
以 Man 为例,这三个字符在 ASCII 和 UTF-8 中都各占一个字节。先写出字节的二进制形式,再按 6 位重新分组,最后查表即可得到 TWFu。整个过程只改变数据的表示方式,没有使用密钥,也没有压缩数据。
Man → TWFu
字符: M a n
十进制字节: 77 97 110
8 位分组: 01001101 01100001 01101110
6 位分组: 010011 010110 000101 101110
索引: 19 22 5 46
查表: T W F u不足 3 个字节时,为什么要补 =?
最后一组若不足 3 个字节,就在剩余位的右侧补 0,使其凑够 6 位后查表,再用 = 把输出补到 4 个字符。= 是填充标记,不属于上述 64 个字符,也不代表原始数据中有一个等号或零字节。
| 输入 | 按 6 位分组(末组右侧补 0) | 有效索引 | 带填充的输出 |
|---|---|---|---|
| M(1 字节) | 010011 010000 | 19、16 | TQ== |
| Ma(2 字节) | 010011 010110 000100 | 19、22、4 | TWE= |
| Man(3 字节) | 010011 010110 000101 101110 | 19、22、5、46 | TWFu |
解码时反过来操作:把字符映射回 6 位数值,拼接后按 8 位还原字节,并依据填充去掉编码时补入的尾部位。例如 TQ== 还原为 01001101,也就是 M。部分协议允许省略 =,但必须由收发双方约定,不能随意删除。
为什么 Base64 会变大?
对于 n 个输入字节,带填充的 Base64 长度为 4 × ceil(n / 3) 个 ASCII 字符,其中 ceil 表示向上取整;这里不计换行和 Data URL 前缀。输入较大时,体积增加接近三分之一;短输入的比例可能更高,例如 1 个字节编码后是 4 个字符。如果把大图片直接塞进 JSON,请求体可能会明显膨胀。
Data URL 和纯 Base64 有什么区别?
| 形式 | 例子 | 用途 |
|---|---|---|
| 纯 Base64 | iVBORw0KGgo... | 只包含编码内容 |
| Data URL | data:image/png;base64,iVBOR... | 包含 MIME 类型,可直接用于 img src |
| URL Safe Base64 | 使用 - 和 _ | 常见于 JWT 和 URL 场景 |
常见坑
- 把 Base64 当作加密,导致敏感信息直接暴露。
- 复制时漏掉末尾 = 填充字符,导致解码失败。
- 把 Data URL 当成纯 Base64 传给后端,后端解析失败。
- 图片太大仍然转 Base64,导致页面和接口变慢。
- 混用标准 Base64 和 URL Safe Base64。
文本为什么还涉及字符编码?
Base64 编码的是字节,不是抽象字符。英文 Hello 在 UTF-8 中是 5 个字节,而中文、Emoji 和其它字符会先按 UTF-8 转成不同的字节序列,再进行 Base64。编码方和解码方如果使用不同字符集,Base64 本身即使完全正确,恢复出的文字仍可能乱码。
文本 → UTF-8 字节 → Base64
Base64 → 字节 → 使用同一字符集还原文本什么时候应该用,什么时候不该用?
| 场景 | 建议 | 原因 |
|---|---|---|
| 很小的图标内联到 CSS | 可以考虑 | 减少一次请求,但会增加文本体积 |
| JSON 中传递少量二进制 | 先确认接口约定 | 需要明确 MIME 类型、长度和大小限制 |
| 大图片或视频 | 不要内联 | 体积膨胀、内存占用和解析成本都很高 |
| 密码、token、个人信息 | 不能当作保护措施 | 解码无需密钥,拿到字符串就能还原 |
解码失败时先确认是否混入 Data URL 前缀、空格或换行,再检查使用的是标准还是 URL Safe 字母表。末尾填充可以按协议省略,但接收方必须明确支持;不要仅靠手工补等号猜测损坏内容。