Base64 是编码不是加密:什么时候该用,什么时候不该用
5Lit5paH5rWL6K+V 这种字符串随处可见——JWT 里、邮件附件里、图片的 data URI 里。很多人以为它"加密"了内容,其实只要复制粘贴到任何一个解码工具就能还原。Base64 只是编码,不提供任何保密性。
为什么需要它
根本原因:有些通道只能传 ASCII 文本。
- 早期 SMTP 邮件只支持 7 位 ASCII,发不了二进制附件
- URL 里不能直接出现空格、
+、/、&等字符 - JSON 字符串里不能塞裸的二进制字节
Base64 把任意字节流重新映射到 64 个安全字符(A–Z、a–z、0–9、+、/),末尾用 = 补齐,于是二进制就能安全地走文本通道了。
原理:3 字节变 4 字符
每 3 个字节(24 位)拆成 4 组、每组 6 位,每组对应一个字符。24 ÷ 6 = 4,不多不少。
原始字节: 01100010 01100001 01110011
重新分组: 011000 100110 000101 110011
对应字符: b m F z
所以 bas 编码后是 YmFz。末尾不够 3 字节时补 =:剩 1 字节补两个 ==,剩 2 字节补一个 =。
体积会膨胀约 33%
3 字节变 4 字符,4/3 ≈ 1.33。一个 10MB 的文件 Base64 之后约 13.3MB。这就是为什么图片转 data URI 内嵌进 HTML 会让页面变大——小图标还可以,大图绝不该这么干。
中文为什么容易乱码
Base64 处理的是字节,不是字符。而"中文"这两个字在 UTF-8 下是 6 个字节,在 GBK 下是 4 个字节。同一段文字,编码方式不同,Base64 结果完全不同。
所以解码时必须知道原始编码:用 UTF-8 编码的内容,必须用 UTF-8 解码,否则就是乱码。本站在处理时固定按 UTF-8 走,这是目前的事实标准。
常见的正确用法
- JWT 的 header 和 payload —— 用 Base64URL(把
+换-、/换_、去掉=) - 邮件附件 —— MIME 的 Content-Transfer-Encoding
- data URI ——
data:image/png;base64,... - HTTP Basic 认证 ——
user:pass编码后放 Authorization 头
三种典型误用
① 拿它当加密
把密码 Base64 一下存数据库——等于明文存。任何拖库的人花一秒钟就能还原。这是一个真实发生过的历史事故(某些老系统至今还在这么干)。
② 用它传大文件
体积膨胀 33%,还要额外占内存做编解码。大文件应该走二进制通道(multipart、S3 预签名 URL 等)。
③ 在 URL 里用标准 Base64
标准 Base64 含 + 和 /,在 URL 中会被转义或截断。要用 Base64URL 变体。
判断标准很简单:如果内容需要保密,用 AES 或 TLS;如果只是为了让二进制能走文本通道,才用 Base64。两者完全不是一回事。