Base64是什么?
个人理解:Base64
是一种编码方式,和ASCll
一样,只是一种编码方式而已,但是两者用到的场景不同。
我看到百度百科上的Base64解释上有这样一段话:
采用Base64编码具有不可读性,需要解码后才能阅读
总觉得‘阅读‘这个词怪怪的,在我碰到的业务场景中,列如图片的Base64
化传输、秘钥密文的Base64
化保存等,其原内容都不是需要人阅读的,真正的’阅读‘者都是机器。
思考Base64产生的原因
思考一个场景:对一段文字进行加密,并传输给服务端。
我们一般先会将这段文字转成二进制数据,然后通过调用系统的加密算法,然后得到一串新的二进制数据,那么如何把这段二进制数据传给服务端呢?
平时我们和服务端传输的数据基本都是utf8
格式的,那么这段二进制数据能直接转成utf8
格式呢?显然是不可能的,utf8
的每个字节前几位的bit都是有特殊含义的(具体看utf8
的生成规则),但是加密得到的二进制数据肯定输无序的,所以最好将密文的二进制数据先转成一种能被utf8
编码的格式,然后就能和服务端进行utf8
格式的通信了
我们来看看平时常常提到的几种编码格式。
先看看utf16
和utf32
,其实他们和utf8
一样,都是对Unicode
码的一种编码。我们从电脑屏幕上看到的每一个字,每一个符号,甚至有些表情都对应一个Unicode
码,那么可以用Unicode
码编码密文二进制数据么?答案是不可以。拿utf32
举例,它其实就是用4个字节表示一个Unicode
码,但4个字节有多少种组合呢?种,Unicode
码的个数只是其中的一部分,但是Unicode
码并不是固定的,它每年还在增加。如果密文数据正好落在Unicode码没有的地方,系统就展示不出来了。而且如果真有一段密文用utf16
展示,里面出现了英文、中文、韩文、数学符号、表情等,你会不会疯掉(手动滑稽)
用ASCll
码表示,似乎是一个很好的注意,因为ASCll
码已经排满,能做到二进制和符号一一对应的关系。但为什么不可以呢,或者说有什么不方便呢?一方面ASCll
码中有许多特殊字符,列如'
、"
、\
等等,在展示的时候,有些地方需要加转义符,有些地方不需要添加,会比较混乱。另一方面ASCll
码排在前面的一些位置并不是符号能展示出来,列如7号位的响铃。
其实到这里离Base64
的产生已经很接近了。如果我们把ASCll
码中那些不能展示出来的位置,和一些特殊字符的位置去掉,形成一种新的编码,那就能很好的展示出密文内容了。基础的ASCll
码占7个bit位,如果去掉一些,那新的编码格式就用6个bit位好了,。Base64
就应运而生了。
当然,上面都是我个人的理解。Base64
算法主要最早用于解决电子邮件传输问题。在早期,由于历史问题,电子邮件只允许传输ASCII码字符。当传输非ASCII码时,网关很可能将非ASCII码的二进制位调整,即将非ASCII码的8位二进制的最高位设为0。当用户收到邮件时,可想而知,收到的就是 一份乱码的邮件。
Base64的规则
所谓的Base64
,就是64个符号来表示6个bit位的二进制流。这64个符号分别为a-z,A-Z,0-9及+
和/
。这里有张对照表
索引 | 符号 | 索引 | 符号 | 索引 | 符号 | 索引 | 符号 |
---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w |
1 | B | 17 | R | 33 | h | 49 | x |
2 | C | 18 | S | 34 | i | 50 | y |
3 | D | 19 | T | 35 | j | 51 | z |
4 | E | 20 | U | 36 | k | 52 | 0 |
5 | F | 21 | V | 37 | l | 53 | 1 |
6 | G | 22 | W | 38 | m | 54 | 2 |
7 | H | 23 | X | 39 | n | 55 | 3 |
8 | I | 24 | Y | 40 | o | 56 | 4 |
9 | J | 25 | Z | 41 | p | 57 | 5 |
10 | K | 26 | a | 42 | q | 58 | 6 |
11 | L | 27 | b | 43 | r | 59 | 7 |
12 | M | 28 | c | 44 | s | 60 | 8 |
13 | N | 29 | d | 45 | t | 61 | 9 |
14 | O | 30 | e | 46 | u | 62 | + |
15 | P | 31 | f | 47 | v | 63 | / |
具体来说,转换方式可以分为四步。
- 第一步,将每三个字节作为一组,一共是24个二进制位。
- 第二步,将这24个二进制位分为四组,每个组有6个二进制位。
- 第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节。
- 第四步,根据下表,得到扩展后的每个字节的对应符号,这就是Base64的编码值。
举一个具体的实例,演示英语单词Man如何转成Base64编码。
image.png
- 第一步,"M"、"a"、"n"的ASCII值分别是77、97、110,对应的二进制值是01001101、01100001、01101110,将它们连成一个24位的二进制字符串010011010110000101101110。
- 第二步,将这个24位的二进制字符串分成4组,每组6个二进制位:010011、010110、000101、101110。
- 第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节:00010011、00010110、00000101、00101110。它们的十进制值分别是19、22、5、46。
- 第四步,根据上表,得到每个值对应Base64编码,即T、W、F、u。
因此,Man的Base64编码就是TWFu。
如果字节数不足三,则这样处理:
- 二个字节的情况:将这二个字节的一共16个二进制位,按照上面的规则,转成三组,最后一组除了前面加两个0以外,后面也要加两个0。这样得到一个三位的Base64编码,再在末尾补上一个"="号。
比如,"Ma"这个字符串是两个字节,可以转化成三组00010011、00010110、00010000以后,对应Base64值分别为T、W、E,再补上一个"="号,因此"Ma"的Base64编码就是TWE=。 - 一个字节的情况:将这一个字节的8个二进制位,按照上面的规则转成二组,最后一组除了前面加二个0以外,后面再加4个0。这样得到一个二位的Base64编码,再在末尾补上两个"="号。
比如,"M"这个字母是一个字节,可以转化为二组00010011、00010000,对应的Base64值分别为T、Q,再补上二个"="号,因此"M"的Base64编码就是TQ==。
网友评论