Last Updated: 2024-03-18 14:22:37 Monday
-- TOC --
所谓Base64编码,就是使用64个特别选出的ASCII字符来表示任意字符串。由于采用6bit编码,所以正好只需要64个字符。
计算机系统每个Byte长8Bit,通过3个byte=24bit=4个Base64字符
的方式进行转换,转换后size增大33.33%
,即3字节变成了4字节。如果经过压缩,实际size的增加将会微不足道。有大量应用场景,需要支持任意Binary Data与Text Data之间的互转,Base64编码几乎无处不在。
有些网络传输协议并不支持所有的字节编码,例如传统的Email邮件服务器,只支持可见字符的传送,像ASCII码的控制字符就不能通过邮件传送。这样用途就受到了很大的限制,比如图片二进制流的每个字节不可能全部是可见字符,所以就传送不了。一个解决方法就是在不改变传统协议的情况下,做一种扩展方案来支持任意二进制字节流的传送。把不可打印的字符通过可打印字符来表示,问题就解决了。Base64编码应运而生,Base64就是一种基于64个可打印字符来表示二进制数据的表示方法。
Base64 | 字符 | ASCII | Base64 | 字符 | ASCII | Base64 | 字符 | ASCII | Base64 | 字符 | ASCII |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | A | 65 | 16 | Q | 81 | 32 | g | 103 | 48 | w | 119 |
1 | B | 66 | 17 | R | 82 | 33 | h | 104 | 49 | x | 120 |
2 | C | 67 | 18 | S | 83 | 34 | i | 105 | 50 | y | 121 |
3 | D | 68 | 19 | T | 84 | 35 | j | 106 | 51 | z | 122 |
4 | E | 69 | 20 | U | 85 | 36 | k | 107 | 52 | 0 | 48 |
5 | F | 70 | 21 | V | 86 | 37 | l | 108 | 53 | 1 | 49 |
6 | G | 71 | 22 | W | 87 | 38 | m | 109 | 54 | 2 | 50 |
7 | H | 72 | 23 | X | 88 | 39 | n | 110 | 55 | 3 | 51 |
8 | I | 73 | 24 | Y | 89 | 40 | o | 111 | 56 | 4 | 52 |
9 | J | 74 | 25 | Z | 90 | 41 | p | 112 | 57 | 5 | 53 |
10 | K | 75 | 26 | a | 97 | 42 | q | 113 | 58 | 6 | 54 |
11 | L | 76 | 27 | b | 98 | 43 | r | 114 | 59 | 7 | 55 |
12 | M | 77 | 28 | c | 99 | 44 | s | 115 | 60 | 8 | 56 |
13 | N | 78 | 29 | d | 100 | 45 | t | 116 | 61 | 9 | 57 |
14 | O | 79 | 30 | e | 101 | 46 | u | 117 | 62 | + | 43 |
15 | P | 80 | 31 | f | 102 | 47 | v | 118 | 63 | / | 47 |
Base64编码,就是全部英文字母的大小写,加上10个数字,再加上+和/两个符号。(26*2+10+2=64)
实际上ASCII中可显示字符比64要多,我们完全可以灵活定制Base64编码中的字符,或者在Base64的基础上,叠加一些私有的加密解密算法。
每3个byte一组,转换成4个字节的base64编码,转换后每个字节只有低6bit有效。
地址从右到左,从低到高,3个字节:
c7c6c5c4c3c2c1c0 | b7b6b5b4b3b2b1b0 | a7a6a5a4a3a2a1a0
拆成4个base64字节:
c5c4c3c2c1c0 | b3b2b1b0c7c6 | a1a0b7b6b5b4 | a7a6a5a4a3a2
最后转4字节ASCII编码
如果要编码的字节流不是3的倍数,最后会剩下1个或2个字节怎么办?
在进行Base64编码之前,先用\x00
字节流在末尾补足,做Base64编码,最后在base64编码的末尾加上1个或2个=
号,表示补了多少\x00字节,解码的时候反过来。
>>> import base64
>>> base64.b64encode(b'abcd')
b'YWJjZA=='
>>> base64.b64decode(b'YWJjZA==')
b'abcd'
abcd要补两个\x00,因此产生的base64编码有两个=号。(看到末尾带=号的字符串,就要想到可能是base64编码过的)
去掉base64编码的=号,如何解码?
由于=号字符也可能出现在Base64编码中,但=号用在URL、Cookie里面会造成歧义,所以,很多Base64编码后会把=去掉。去掉=号之后,如何解码?
因为Base64是把3个字节变为4个可显示字节,所以,Base64编码的长度永远是4的倍数,因此,只需要加上=号,把Base64字符串的长度变为4的倍数,就可以正常解码了。
将图片的Base64编码数据直接嵌入HTML页面内容,采用如下方法:
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///666AA/123456asdWEFDVED" />
这种方法可以减少HTTP请求响应的数量,大部分网站都会将size较小的图片用这种方式嵌入网页。
Data URI Scheme
有一个通用的format:
data:<content type>;base64,<base64 data>
由于标准的Base64编码后可能出现字符+和/,在URL中就不能直接作为参数,所以出现一种"url safe"的base64编码,其实就是把字符+
和/
分别变成-
和_
。
>> base64.urlsafe_b64decode(b'xy-_')
b'\xc7/\xbf'
>>> base64.urlsafe_b64decode(b'xy+/')
b'\xc7/\xbf'
>>> base64.b64decode(b'xy+/')
b'\xc7/\xbf'
前面的代码示例,展示了base64模块的基本使用,同时此模块也可以在命令行直接使用:
$ echo '12345' | python3 -m base64
MTIzNDUK
$ echo '12345' | python3 -m base64 | python3 -m base64 -d
12345
本文链接:https://cs.pynote.net/sf/202109125/
-- EOF --
-- MORE --