目录
毫无疑问,base64是一种数据的编解码方法(算法)。更具体地描述,它是一种从二进制(blob)到字符的编解码。base64将3个字节,共24bits的数据,编码为6个bits为一个单元的4个数据单元。
如何解释呢?
通俗的讲,就是对原始的binary数据,按照每3个字节的序列进行分组。如果binary数据不是3个字节的整数倍,需要进行补全。因此,base64编码后的字符长度,必定是3字节(24比特)的整数倍。具体规范,见下文。
由定义可知,base64编码的每个字符是6个bits表示,因此总共是2^6 = 64个有效数据字符。实际上,还额外需要一个做padding的字符,base64规范中使用’=‘字符来对3字节对齐的尾部做padding补足。
目前,base64的编解码规范,主要使用RFC4648标准,其编码使用的可打印字符如下图。
需要注意的是:
按照二进制计算出的十进制索引的字符进行填充,例如:十进制的1就对应了字符'A'
编码后,数据长度增加。因为编码后用ASCII字符(8bits)来表示一个6bits的二进制数据,因此数据长度至少为原来的4/3倍。
二进制数据不足3字节的整数倍时,需要进行尾部填充(padding)。
为什么是3字节的整数倍?因为二进制数据都是以字节(8bits)为单位的,而6和8的最小公倍数是24(bits),也即3字节。
关于补全,有两种情况
单字节尾部,剩余不足6bits时,需要先填0补全跨字节边界的6个bits
完整字节的尾部直接按照每6bits补一个'='字符
等号仅会在尾部出现,且最多两个等号。
示例1
"Man"的ASCII二进制
恰好是24bits(3字节),因此base64编码为4个字符:TWFu
,编码后数据长度4字节(32bits)。
示例2
"Ma"的ASCII二进制
16bits(2字节)长度,需要填充8bits(1字节)长度。可以看到第2个字节(a)的尾部不足6bits,因此先填0补足第3个6bits需要的位数。随后直接填充编码后的最后一个6bits为'='符号。最终base64编码为4个字符:TWE=
,编码后数据长度4字节(32bits)。
示例3
"M"的ASCII二进制
8bits(1字节)的长度,需要填充16bits(2字节)的长度。可以看到第1个字节(M)的尾部不足6bits,因此先填0不足第2个6bits需要的位数,随后直接填充编码后的最后两个6bits位'='符号。最终base64编码为4个字符:TQ==
,编码后数据长度4字节(32bits)。
编码
- # echo -n "Man" | base64
- TWFu
解码
- # echo -n "TQ==" | base64 -d
- M
- # python
- Python 2.7.17 (default, Jul 1 2022, 15:56:32)
- [GCC 7.5.0] on linux2
- Type "help", "copyright", "credits" or "license" for more information.
- >>> import base64
- >>> base64.b64encode(b'Man')
- 'TWFu'
- >>> base64.b64decode(b'TQ==')
- 'M'
- >>>
万维网文本协议中,嵌入二进制数据
图片:
二进制blob的字符串表示
邮件SMTP服务
为什么文本协议(前端开发)中使用base64?
文本,以及超文本协议的某些字符具有特殊含义。例如:http和xml中的‘<’, ‘/’,‘>’。直接传输二进制,二进制中会被文本协议解释成特殊字符,从而破坏文本协议的正确性,导致无法解析。
在开发中,实际经常使用base64编码。例如
前端经常将小图片处理成base64
博客编辑器,复制黏贴过来的图片,通常处理成base64,填到标签中
加密或文件的hash生成的二进制,也转换成base64来进行传输或打印(毕竟不是所有二进制都可打印)。
编码后数据长度增加
只能用于非加密使用
https://en.wikipedia.org/wiki/Base64
关于作者:
犇叔,浙江大学计算机科学与技术专业,研究生毕业,而立有余。先后在华为、阿里巴巴和字节跳动,从事技术研发工作,资深研发专家。主要研究领域包括虚拟化、分布式技术和存储系统(包括CPU与计算、GPU异构计算、分布式块存储、分布式数据库等领域)、高性能RDMA网络协议和数据中心应用、Linux内核等方向。
专业方向爱好:数学、科学技术应用
关注犇叔,期望为您带来更多科研领域的知识和产业应用。
内容坚持原创,坚持干货有料。坚持长期创作,关注犇叔不迷路。