Base64常用于对电子邮件、短信、URL等进行编码和传输,在Python和Mysql中都有实现方式。
但这里要说的是它编码的基本原理和步骤。
1. 首先相信大家都会看到这个表:Base64对应的字符表,一共64个字符,包括26个字母的大小写、10个阿拉伯数字、+号和/号;附:(还有一个' =' 号一般用于后缀)。
2. Base64并不加密信息,因为它属于编码方式,不属于加密系统;可以随时对其信息进行解码。
3. Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64是一种基于上述64个可打印ASCII字符来表示二进制字节流数据的方法,还有' =' 号用于后缀。
Base64编码是一种从二进制到字符的过程,解码则相反。
4. 其编码规则主要有:
- 把3个字节变成4个字节。
- 每76个字符加一个换行符。
- 结束符也要进行处理。
5. 编码步骤:
(1)对原始数据,分字节,求二进制字符串;
(2)对二进制串,6位为一组进行分组,不足末尾补0;
(3)在各分组前面补2个0成8位,求各分组的十进制值,根据十进制对应上表找编码字符;
(4)字节数对3取余数,余数为0,不加等号;余数为1,在上述编码符号串的末尾加2个等号;余数为2,末尾加1个等号。
6. 编码示例:
(1)原始数据是英文字符,sss = 'SE'
流程:
首先,求取 'SE' 的二进制编码(utf-8和ASCII等在英文时一致),sss.encode('utf-8') = b 'SE',b表示bytes类型,'SE'只是打印出来的符号,实际上其二进制是ASCII码的大写'S'和'E'的编码连接而成:01010011(二进制,其十进制是83,'S'),01000101(二进制,其十进制是69,'E')—— 即,将输入字符串按字节切分,取得每个字节对应的二进制值(若不足8比特则高位补0);
其次,将该二进制字符串:01010011 01000101,按照6位一组进行切分(因为2的6次方刚好是64,在Base64的编码范围内),最后一组如果不足6位则末尾补0;于是得到:010100 110100 010100 的3组二进制串。
然后,各自在前面补2个0得到:00010100 00110100 00010100,转化成十进制为:20,52,20;对应到上面的表中得到:'U0U',注意中间这个是0。
最后,将N字节的原始数据,每个字节8位,按照6位一组进行划分,(而6和8的最小公倍数为24),所以要划分的二进制位数必须是24的倍数(或者字节数是3的倍数),而这里的 'SE' 原始数据只有2个字节,2%3=2,所以在结尾需要补上1个等号 '='。
综合以上得到:'U0U='
注:由于某字节数M%3的值,(即M除以3的余数)只有0,1,2共三种情形,0表示整除(不用加等号 '=');那么余数为1,则要加上2个等号 '=';余数为2则要加上1个等号 '='。
(2)原始数据是中英文,sss='线?' ,这里的问号是英文
流程:
同理,首先求取sss字符串的二进制编码,sss.encode('utf-8') = b'xe7xbaxbf?',b表示bytes字节流类型,x表示十六进制,写的清楚一点就是:e7 ba bf ? ;
则该字符串的二进制数据(进制转换)为:11100111(e7)10111010(ba)10111111(bf)00111111(英文?的ASCII码,二进制);
其次,将上述字符串6位一组进行划分,不足补0,得到:111001 111011 101010 111111 001111 110000;
然后各自在前面补2个0得到:00111001 00111011 00101010 00111111 00001111 00110000,十进制值也就是:57,59,42,63,15,48;对应上表也就是:'57q/Pw'
最后,原始数据共4个字节,4%3=1,所以加上两个等号 '='。
综合以上得到:'57q/Pw=='
import base64 sss = 'SE' aaa = base64.b64encode(sss.encode('utf-8')) #base64编码前,需要把数据变成字节流bytes print('aaa:',aaa) bbb = base64.b64decode(aaa) #解码 print('bbb:',bbb)
7. 解码:
解码就是编码的逆过程:
(1)先去掉等号;
(2)再根据编码表,找编码字符对应的编码值;
(3)取各编码值的8位二进制值,去掉每个二进制的前2位的0值,然后连接形成二进制串;
(4)对上述二进制串,从前到后,每8位构成一个字节的数据;多余的末尾0值去掉;
(5)此时得到的就是原始数据的二进制编码;再根据编码方式(例如 utf-8)等进行解码。
8. 解码示例:
对于上述编码的 'U0U=':
首先,去掉等号 '=',得到 'U0U';
其次,根据编码表,找到对应的编码值:20,52,20;
然后,取8位二进制值为:00010100 00110100 00010100;每一个去掉前面2位的0,得到:010100 110100 010100;
最后,从前到后,每8位构成一个字节数据,去掉末尾多余的0:010100 110100 010100;所以末尾2个0去掉,此时得到的就是原始数据的二进制编码,可以继续utf-8解码形成原始数据;
9. Base64编码的python代码
# python 实现base64编码 def base64_func(str_): # str_为原始字符串 oldstr = '' newstr = [] base_str = '' base64_list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P','Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f','g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v','w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'] # 首先将原始字符串转化为二进制字节流,这里用的是 utf-8编码,也可以用bytes函数实现 byte_str = str_.encode('utf-8') #会形成一个或多个字节的二进制字节流,是可以遍历的(可迭代),并且遍历的结果是以十进制显示的 for ii in byte_str: oldstr = oldstr + '{:08}'.format(int(bin(ii).replace('0b', ''))) #用bin转换后是0b开头的,所以先把0b去掉;int将字符串转化成数值型,然后再在前面补0补齐成8位字符串{:08},并各字节进行连接 #把转换后且连接的二进制按照6位一组分组,最后一组不足6位的末尾补0 for jj in range(0, len(oldstr), 6): #第三位6相当于步长 newstr.append('{:0<6}'.format(oldstr[jj:jj + 6])) #{:0<6}中的<表示左对齐,0表示填充0;oldstr[jj:jj + 6]中,如果jj+6超出字符串长度,则会直接取到末尾,列表也是 #在base_list中找到对应的字符,拼接 for ss in range(len(newstr)): base_str += base64_list[int(newstr[ss], 2)] #二进制先转十进制,查找 #判断base_str字符串结尾补几个等号‘=’ if len(str_) % 3 == 1: base_str += '==' elif len(str_) % 3 == 2: base_str += '=' return bytes(base_str,'utf-8') # 也可直接返回:base_str ss = base64_func('线?') print(ss)
# 欢迎交流
参考: