Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法,由于 2^6=64,所以每 6 个比特为一个单元,对应某个可打印字符。
Base64 常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,包括 MIME 的电子邮件及 XML 的一些复杂数据。
Base64 编码要求把 3 个 8 位字节(3*8=24)转化为 4 个 6 位的字节(4*6=24),之后在 6 位的前面补两个 0,形成 8 位一个字节的形式。如果剩下的字符不足 3 个字节,则用 0 填充,输出字符使用 =,因此编码后输出的文本末尾可能会出现 1 或 2 个 =。例如:
“A” --> QQ== “AB” --> QUI= “ABC" --> QUJD
为了保证所输出的编码位可读字符,Base64 制定了一个编码表,以便进行统一转换。编码表的大小为 2^6=64,这也是 Base64 名称的由来。在 Base64 中的可打印字符包括字母 A-Z、a-z、数字 0-9,这样共有 62 个字符,此外两个可打印符号在不同的系统中而不同。如下表:
Base64 由于以上优点被广泛应用于计算机的各个领域,然而由于输出内容中包括两个以上 “符号类” 字符(+, /, =),不同的应用场景又分别研制了 Base64 的各种 “变种”。为统一和规范化 Base64 的输出,Base62x 被视为无符号化的改进版本。
Base64 编码具有以下特点:
(1)编码后的数据长度总是比原始数据长约 1/3。
(2)编码后的数据可以包含 A-Z、a-z、0-9 和两个额外字符的任意组合。
(3)Base64 编码是一种可逆的编码方式,可以通过解码还原原始数据。
Base64 编码的基本步骤:
(1)将数据划分为 3 个字节一组(24位)。
(2)将每个字节转换为 8 位二进制形式。
(3)将 24 位数据按照 6 位一组进行划分,得到 4 个 6 位的组。
(4)将每个 6 位的组转换为对应的 Base64 字符。
(5)如果数据不足 3 字节,进行填充。
(6)将所有转换后的 Base64 字符连接起来,形成最终的编码结果。
下面以 “hello” 字符串为例演示 Base64 编码,过程如下:
(1)将 “hello” 字符串转换成二进制,二进制如下:
01101000 - 01100101 - 01101100 - 01101100 - 01101111
(2)将转换后的二进制按照 6 个位为一组进行分组,如下:
01101000 - 01100101 - 01101100 - 01101100 - 01101111 原始二进制 011010 - 000110 - 010101 - 101100 - 011011 - 000110 - 1111 按六位分组
(3)将转换为 6 个位一组的二进制进行补全,前面添加两个 00,如下:
011010 - 000110 - 010101 - 101100 - 011011 - 000110 - 1111 补全前 00011010 - 00000110 - 00010101 - 00101100 - 00011011 - 00000110 - 00111100 补全后
(4)将补全后的二进制转换为十进制,如下:
00011010 - 00000110 - 00010101 - 00101100 - 00011011 - 00000110 - 00111100 补全后 26 - 6 - 21 - 44 - 27 - 6 - 60 对应的十进制数
(5)根据(4)得到的十进制数从 Base64 字符表中按下标找到对应的字符,如:下标 0 对应字符 A,如下:
26 - 6 - 21 - 44 - 27 - 6 - 60 对应的十进制数 a - G - V - s - b - G - 8 映射后的字符
(6)将上面所有映射后的字符连接起来,得到:aGVsbG8
(7)最后一步,得到的字符串 aGVsbG8 的长度必须是 4 的倍数,这里的 aGVsbG8 长度为 7,不是 4 的倍数,需要加一才是 4 的倍数。因此,这里需要添加一个 “=” 字符。由于这个原因,我们经常会看到 Base64 编码后的字符串尾部有一个或两个 “=” 字符。
最终结果:aGVsbG8=
Base64 的解码过程和编码过程刚好相反,还是以上面的 “hello” 字符串为例:
(1)字符串 “hello” 编码后的原文为:aGVsbG8=
(2)去掉编码后字符串尾部的 “=” 字符串,如下:
aGVsbG8= 取下前 aGVsbG8 取消后
(3)将取消 “=” 后的字符串转换成二进制字符串,如下:
aGVsbG8 字符串 00011010 - 00000110 - 00010101 - 00101100 - 00011011 - 00000110 - 00111100 字符串对应的二进制
(4)将字节二进制前面的两个 0 去掉,如下:
00011010 - 00000110 - 00010101 - 00101100 - 00011011 - 00000110 - 00111100 去掉前 011010 - 000110 - 010101 - 101100 - 011011 - 000110 - 111100 去掉后
(5)将去掉前两个 0 的二进制重新按照 8 位一组进行分组,如下:
011010 - 000110 - 010101 - 101100 - 011011 - 000110 - 111100 分组前 01101000 - 01100101 - 01101100 - 01101100 - 01101111 - 00 分组后
(6)去掉最后多余的二进制,不能组成 8 个一组的二进制,如下:
01101000 - 01100101 - 01101100 - 01101100 - 01101111 - 00 裁剪前 01101000 - 01100101 - 01101100 - 01101100 - 01101111 裁剪后
(7)将二进制转换成对应的字符,如下:
01101000 - 01100101 - 01101100 - 01101100 - 01101111 二进制 h - e - l - l - o 对应的字符
(8)将转换后的字符连接起来,最终结果为:hello