Base64编码原理分析

来源:互联网 发布:国企混日子 知乎 编辑:程序博客网 时间:2024/06/05 18:23

之前看到了Base64编码,但是对其原理一直模模糊糊,不大明白,今天决定要搞懂了!

先上图:

image

其实,我没怎么看懂,008B5DCB

百度了下,从头开始解释:

一、计算机容量单位及单位换算

1、b(又称:bit,位),是计算机中最小的单位,有两个值:0,1;

注意:但这个b和大写B的不是一个单位。

2、B(又称:Byte,字节)是计算机中最基本的计量单位。

两者的关系:1B=8b,一个字节=8个位

二、编码问题

1. ASCII码

在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。

上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为ASCII码,一直沿用至今。

ASCII码一共规定了128个字符的编码,比如空格"SPACE"是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。

就目前来说,英语大小写字母,0-9数字和 +  /,总共64个字符,都可以用ASCII码来表示;

就js来说,可以用charCodeAt()方法求字符的ASCII码,不过是10进制,然后可以用toString(进制)方法,转成相应的进制:

比方说:

image

+ 的ASCII码为43,转成2进制为 101011,这里2进制不足8位,前面补0就是:00101011。

所以,英语大小写字母,0-9数字和 +  /,总共64个字符,都可以用ASCII码来表示,进一步,都可以表示成 8 位二进制。

三、Base64编码

Base64编码,就是将,三个字节(也就是3*8=24位)的数据,变成6个bit为一组的组集,也就是4组*6位,还是24位;既然每组只有6位,所以最多只能表示64个数,从000000到111111;而这64个数就是,52个大小写字母、10个数字0-9、+、/。

举个例子:字符串  a:a  ,总共3个字节,每个字节用二进制表示分别为,

字符 ASCII码(10进制) 二进制(不足8位高位补0) a 97                                      01100001 :  58                                       00111010 a   97                                      01100001

所以字符 a:a 用二进制表示就是  011000010011101001100001

按照Base64编码规则,我们要把 011000010011101001100001,拆成4组,每组6位,那就是 011000 010011 101001 100001,把他们转成10进制,就是24 19 41 33,可能有人问,怎么把2进制,转为10进制呢?

在js里,就是,parseInt(字符串,进制);上面的四组就是:

image

然后根据下面的Base64字母表,就可以得出,24 19 41 33,分别为 Y T p h;所以 a:a 按照Base64编码结果为 YTph,明白了么?

image

说到这里呢,其实还没完,前面应该有人已经想到了,如果一个字符串的长度不是3的n倍个字节呢?嗯嗯,比如4个字节?如 :

a:aa

呐,咱们照例,先把每个字节转成ASCII码,然后转成二进制,就是: 字符 ASCII码(10进制) 二进制(不足8位高位补0) a 97                                      01100001 :  58                                       00111010 a   97                                      01100001 a       97                                      01100001

放在一起就是:

01100001001110100110000101100001

然后每3个字节,也就是24位,按照Base64编码规则,每组6位,这里有3*8+1*8就是32位,所以就是,5组+2位,就是下面这样:

011000 010011 101001 100001 011000 01

但是,Base64编码是每3个字节一转,也就是每24位一转,不足24位的就在序列末尾填充零位,补到长度为24的倍数为止,像上面总共32位,所以要补到48位,就是这样:

011000 010011 101001 100001 011000 01xxxx xxxxxx xxxxxx

注意:补充位以x表示;

按照Base64编码规则,

对已填充的二进制串进行编码时,任何完全填充(不包含原始数据中的位)的6 位组都由特殊的第65 个符号“=”表示。如果6 位组是部分填充的,就将填充位设置为0。

因此上面的48位二进制实际就是:

011000 010011 101001 100001 011000 01xxxx ==

对吧?咱们逐个解密(每组先转成10进制,然后对照Base-64字母表查)就是:

Y T p h Y 01xxxx ==

这里咱们就遇到问题了,01xxxx 这个怎么转?把x当成0么?对!就是这样!

所以 01xxxx 就是 010000 ,也就是10进制的,16

image

对照Base-64字母表,就是 Q,

综上,

a:aa  经过Base64编码结果就为  YTphYQ

这,就是Base64编码原理,解码就反向而行!

不过,在js里,本身提供了Base64编码解码的方法,还是以上面 a:aa 为例,就是

image

行文仓促,如有错误之处,欢迎拍砖指正!