学习Base64编码

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编码几乎无处不在。

为什么需要Base64编码?

有些网络传输协议并不支持所有的字节编码,例如传统的Email邮件服务器,只支持可见字符的传送,像ASCII码的控制字符就不能通过邮件传送。这样用途就受到了很大的限制,比如图片二进制流的每个字节不可能全部是可见字符,所以就传送不了。一个解决方法就是在不改变传统协议的情况下,做一种扩展方案来支持任意二进制字节流的传送。把不可打印的字符通过可打印字符来表示,问题就解决了。Base64编码应运而生,Base64就是一种基于64个可打印字符来表示二进制数据的表示方法。

Base64编码表

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的基础上,叠加一些私有的加密解密算法。

如何转换成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的倍数,就可以正常解码了。

Data URI Scheme

将图片的Base64编码数据直接嵌入HTML页面内容,采用如下方法:

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///666AA/123456asdWEFDVED" />

这种方法可以减少HTTP请求响应的数量,大部分网站都会将size较小的图片用这种方式嵌入网页。

Data URI Scheme有一个通用的format:

data:<content type>;base64,<base64 data>

url safe的base64编码(Base64url)

由于标准的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'

Python3的base64模块

前面的代码示例,展示了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 --