开发 · 阅读约 4 分钟 ·

Base64 详解:它的用途,以及为什么它不是加密

Base64 出现在邮件、data URI、API 请求头和 JWT 中。本文讲解它的原理、为什么数据会变大三分之一,以及为什么它什么都藏不住。

Base64 在软件中无处不在:邮件附件、嵌在 CSS 里的图片、HTTP Basic 认证的 Authorization 请求头,以及 JWT 的各个部分。它只有一个任务:只用安全的文本字符,写出任何数据,包括二进制字节。

工作原理

Base64 每次取三个字节(24 位),把它们分成四组,每组 6 位。每组是 0 到 63 之间的一个数,对应 64 个字符之一:A-Z、a-z、0-9、+ 和 /。如果输入不能被三整除,就在末尾用 = 补齐。

文本    M        a        n
字节    01001101 01100001 01101110
6 位    010011 010110 000101 101110
Base64  T      W      F      u       →  TWFu

为什么需要它

许多旧系统,尤其是电子邮件,是为文本设计的,可能会损坏任意字节。Base64 把任何内容都变成普通字符,让它们原样穿过这些通道。代价是体积:每 3 个字节变成 4 个字符,所以编码后的数据大约大 33%。

它不是加密

没有密钥。任何人都能瞬间解码 Base64,所以它什么也藏不住。Basic 认证请求头里的密码(dXNlcjpwYXNz 就是 user:pass)和明文一样暴露。请用 HTTPS 和真正的加密来保护机密,永远不要把 Base64 当作安全措施。

你会遇到的变体

Base64url 把 + 和 / 换成 - 和 _,并且通常省略填充,因此可以安全地用在 URL 和文件名中;JWT 用的就是它。data URI 把编码后的数据直接嵌入代码,例如 data:image/png;base64,iVBOR…,对极小的图片能省一次请求,但会让大图更臃肿。

用数字看体积

n 个字节编码后的长度是 4 × ceil(n / 3) 个字符,所以体积大约增加 33%,如果编码器插入换行,还要再加上换行。

100 KB 的图片   →  约 133 KB 的 Base64
1 MB 的附件     →  约 1.33 MB(邮件里还要加上换行)

解码为什么会失败

  • 缺少填充:有些系统会去掉末尾的 =,严格的解码器就会拒绝输入。补上 =,直到长度是 4 的倍数。
  • 字母表不对:Base64url 用 - 和 _ 代替 + 和 /。用 Base64url 解码器解码,或者先把字符换回来。
  • 换行和空格:邮件(MIME)每 76 个字符就把 Base64 换一行。大多数解码器会忽略换行,但不是全部。
  • 文本编码不对:解码得到的是字节。如果它们本是 UTF-8 文本却被当作 Latin-1 读取,中文、希伯来文和带重音的字母就会变成乱码。

JavaScript 中 btoa 的陷阱

浏览器内置的 btoa() 只接受 Latin-1 字符,遇到中文、希伯来文或表情符号就会报错。先把文本编码成 UTF-8 字节(例如用 TextEncoder),再转成 Base64。

什么时候该用,什么时候不该用

当二进制数据必须经过为文本设计的通道时,Base64 是合适的工具:JSON 和 XML 载荷、电子邮件、data URI 和 HTTP 头部。它不适合用来隐藏数据、压缩数据(体积总会变大),也不适合把大文件存进数据库,那里用二进制列或对象存储更小也更快。如果接收方接受原始字节,就直接发送原始字节。

动手试试

4Dev 的 Base64 编码器会在你输入时实时把文本转成 Base64。它使用 UTF-8,所以中文、表情符号以及任何非英文文本都能正确编码。反向转换请使用 Base64 解码器。

打开 Base64 编码器

LinkedInXFacebook