虽然名字听起来像是某种“64进制”,但实际上它是一种编码方式,不是数学意义上的“进制”
起源背景
Base64 最早起源于电子邮件协议 MIME(Multipurpose Internet Mail Extensions),因为早期的电子邮件系统只能传输 ASCII 文本,不能直接传输二进制数据(如附件)。于是人们发明了 Base64 编码方法,把二进制数据转换成文本形式,从而安全地在网络上传输
标准的 Base64
Base64 不是一种加密算法,而是一种编码方式
就是基于 64 个可打印字符来表示二进制数据的方法:
- 小写字母 a-z
- 大写字母 A-Z
- 数字 0-9
- 符号
+
、/
编码规则
- 把 3 个字节变成 4 个字节
- 每 76 个字符加一个换行符
- 最后的结束符也要处理
如:
- 原字符串
s13
- 转成 ascii 对应:115, 49, 51
- 二进制: 01110011, 00110001, 00110011
- 6 个一组(4 组): 011100, 110011, 000100, 110011
- 计算机一个字节占 8 位,不够高位补 0:00011100, 00110011, 00000100, 00110011
- 得到:28, 51, 4, 51
- 对照表:
czEz
原文的字节数量应该是 3 的倍数,如果这个条件不能满足的话,具体的解决办法是这样的:原文剩余的字节根据编码规则继续单独转(1 变 2,2 变 3;不够的位数用 0 补全),再用 =
补满 4 个字节。
这就是为什么有些 Base64 编码会以一个或两个等号结束的原因,但等号最多只有两个。因为一个原字节至少会变成两个目标字节,所以余数任何情况下都只可能是 0,1,2 这三个数中的一个:
- 如果余数是 0 的话,就表示原文字节数正好是 3 的倍数(最理想的情况)
- 如果是 1 的话,转成 2 个 Base64 编码字符,为了让 Base64 编码是 4 的倍数,就要补 2 个等号
- 同理,如果是 2 的话,就要补 1 个等号
注意
Base64 并非压缩算法,它会将数据体积增加约 33%
应用
场景 | 说明 |
---|---|
图片嵌入到 HTML/CSS 中 | Data URI 方式减少请求 |
JSON 数据中传输二进制信息 | 如头像、加密数据等 |
WebSocket 发送二进制消息 | 避免使用 ArrayBuffer |
二维码生成 | 将图像转为 Base64 存储 |
很多下载类网站都提供“迅雷下载”的链接,其地址通常是加密的迅雷专用下载地址。其实迅雷的“专用地址”也是用 Base64 “加密”的,其过程如下:
- 在地址的前后分别添加
AA
和ZZ
- 对新的字符串进行 Base64 编码
另外 Flashget 的与迅雷类似,只不过在第一步时加的“料”不同罢了,Flashget 在地址前后加的“料”是 [FLASHGET]
而 QQ 旋风的干脆不加料,直接就对地址进行 Base64 编码了
Base64 URL
标准的 Base64 并不适合直接放在 URL 里传输,因为 URL 编码器会把标准 Base64 中的 +
和 /
字符变为形如 %XX
的形式,而这些 %
在存入数据库时还需要再进行转换,因为 ANSI SQL 中已将 %
号用作通配符。
为解决此问题,可采用一种用于 URL 的改进 Base64 编码,它在末尾填充 =
,并将标准 Base64 中的 +
和 /
分别改成了 -
和 _
,这样就免去了在 URL 编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
浏览器提供了 btoa
函数,可以将字符串转换成 Base64 URL 字符串;反之也提供了 atob
函数
node 没有提供这两个函数,可以安装第三方库 atob
和 bota
,或者自己写
Base64 其他变种
另有一种用于正则表达式的改进 Base64 变种,它将 +
和 /
改成了 !
和 -
,因为 +
、/
在正则表达式中都具有特殊含义。
此外还有一些变种,它们将 +
、/
改为 _-
或 ._
(用作编程语言中的标识符名称)或 .-
(用于 XML 中的 Nmtoken)甚至 _:
(用于 XML 中的 Name)。