这篇文章简单介绍一下 Base64 encoding(Base64 编码)的知识。
我们在 Luna Tech | 聊聊计算机的几个基本概念这篇入门文章里面曾经讲过编码和解码的基本概念。
编码(encode) = 符号变成 01
解码(decode) = 01 变成符号
Base64 就是一种编码的方式,只不过 Base64 并不是直接把符号变成 01,而是先把符号变成 01,再用 64 个可打印字符来表示 01。
Base64 是一种基于 64 个可打印的字符来标识二进制数据的标识方法。
让我们用之前的工具来看一下 Base64 encoding。
https://cryptii.com/pipes/text-decimal
Luna
的 base64 encode 结果是THVuYQ==
.
1 个 Byte 有 8 bit;
Base64 一共有 64 个可用字符,2 的 6 次方等于 64,所以每个字符对应 6 bit。
计算 6 和 8 的最小公倍数(质因数分解法)
6 = 2^1*3^1
8 = 2^3
最小公倍数=2^3*3^1=24
先把所有的 Byte 三个一大组(24 bit),再把每组的 24 bit 分为 6 bit 一小组,根据 6 bit 的 Base64 编码表来输出结果。
假设输入是 6 Byte(48 bit),我们先分成两个大组,再把每大组分为 4 个小组,最终输出的结果是 8 个 Base64 编码的字符。
假如除以 3 余 2,那么总共剩余 2*8=16bit,在划分为 6bit 一组的时候就会变成 6,6,4 的情况,这时候我们就要在 4 的那一组最后补 2 个 0。
假如除以 3 余 1,那么总共剩余 1*8=8bit,在划分为 6bit 一组的时候就会变成 6,2 的情况,这时候我们就要在 2 的那一组最后补 4 个 0。
Base64 的最终目标是把所有的 01 都转成 64 个特定的符号,那么这 64 个符号都包括哪些呢?
A-Z(26)
a-z(26)
0-9 (10)
26+26+10 = 62
还有两个呢?
在不同的系统里面这两个“多余”的字符是不一样的。
比如在 MIME 格式的电子邮件中,加了+
和/
这两个字符,并且还在编码的结果加了=
作为后缀。
输入:Luna
输出:THVuYQ
还记得我们用 Base64 encode 工具输入 Luna
之后得到的结果THVuYQ==
吗?
为什么我们计算的结果少了两个==
?
这里就要隆重介绍一下补位的概念了!
假如我们在分大组的时候,Byte 数量能被 3 整除,那么每个大组最终的输出结果就是 4 个 Base64 的编码结果。
但是在计算Luna
的 Base64 编码过程中,我们发现分大组的时候整除不了,余 1。
虽然我们在第二大组的第二小组补了 4 个 0,但是最终第二大组只能输出 2 个 Base64 编码符号YQ
。
补位就是为了补足第二大组缺少的那两个小组,让第二大组的最终输出结果也有 4 个编码符号YQ==
。
整除余 2 的情况呢?缺的这个大组少了一个小组,所以最终结果是输出 3 个编码符号。
那么我们为了满足 4 的倍数,就要人为给这个大组的输出结果加一个补位符=
。
=
这是根据 Base64 encode 的编码规则来的,你可以把这个补位符定义为 64 个符号之外的任何一个,对于解码的过程来说,补位符存在与否是无所谓的。
”For example, in a very simple network protocol. If unpadded strings are concatenated, it’s impossible to recover the original data because information about the number of odd bytes at the end of each individual sequence is lost. “
假如网络传输协议没法很好的处理丢包的情况(比如 UDP),有了 4 的倍数这个规定之后,一旦发现收到的数据不满足 4 的倍数,就可以丢弃。
比如我们发出去 8 个 Base64 字符,对方只收到 5 个,在已知有补位符的情况下,对方就知道这个信息是不完整的。
假如收到 7 个,而且第七个是
=
的话,还可以自动补足第八位。
Base64 可以有不同的编码方式,你可以自定义 64 个符号,选择额外符号,但是最终输出的符号中可以不显示额外符号。
解码就是编码的反向过程,假如你手头有一个 base64 的编码结果,用 base64 解码就能得到初始符号。
注意:Base64 并不是加密哦,只是一种特殊的编码方式而已~
本文讲了:
希望对大家有所帮助~
特别鸣谢:耐心给我解释原理、答疑的 Imba。
Reference:
https://developer.aliyun.com/article/763589
http://www.ruanyifeng.com/blog/2008/06/base64.html