base64编码是将任意二进制序列编码成ASCII字符(可打印字符)序列的编码方案
在base64编码中,每3个二进制字节编码为4个ASCII字符,也就是将3个字节(24位二进制位)拆分成4个(6个二进制位的)数,再将这4个数根据base64的编码表来映射为4个ASCII字符;对于二进制序列的字节数不是3的倍数的,需要在序列最后补充1个或2个字节0
来对齐3个字节再转换
编码时,以3个字节为单位,转换为4个字符;解码时,以4个字符为单位,转换为3个字节
base64编码表
0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
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 + /
写成C语言数组是这样的
char *table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
拆分过程详解
下图中,BINARY一列i1-i3表示的是转换前的字节,小方格里的数字表示二进制位的位置(大数字表示高位),BEFORE和AFTER分别表示拆分前后的二进制数,o1-o4表示的是拆分后的4个数字
┌───────────────┬───────────────┬───────────────┐
BINARY │i1 │i2 │i3 │
├─┬─┬─┬─┬─┬─┬─┬─┼─┬─┬─┬─┬─┬─┬─┬─┼─┬─┬─┬─┬─┬─┬─┬─┤
BEFORE │7│6│5│4│3│2│1│0│7│6│5│4│3│2│1│0│7│6│5│4│3│2│1│0│
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
AFTER │5│4│3│2│1│0│5│4│3│2│1│0│5│4│3│2│1│0│5│4│3│2│1│0│
├─┴─┴─┴─┴─┴─┼─┴─┴─┴─┴─┴─┼─┴─┴─┴─┴─┴─┼─┴─┴─┴─┴─┴─┤
│o1 │o2 │o3 │o4 │
├───────────┼───────────┼───────────┼───────────┤
BASE64 │table[o1] │table[o2] │table[o3] │table[o4] │
└───────────┴───────────┴───────────┴───────────┘
需要注意的是,从左往右,字节顺序是从低到高的,而二进制数位的顺序是从高到低的
二进制序列"\x01\x02\x03"
将编码成AQID
,过程如下:
┌───────────────┬───────────────┬───────────────┐
BINARY │\x01 │\x02 │\x03 │
├─┬─┬─┬─┬─┬─┬─┬─┼─┬─┬─┬─┬─┬─┬─┬─┼─┬─┬─┬─┬─┬─┬─┬─┤
BEFORE │0│0│0│0│0│0│0│1│0│0│0│0│0│0│1│0│0│0│0│0│0│0│1│1│
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
AFTER │0│0│0│0│0│0│0│1│0│0│0│0│0│0│1│0│0│0│0│0│0│0│1│1│
├─┴─┴─┴─┴─┴─┼─┴─┴─┴─┴─┴─┼─┴─┴─┴─┴─┴─┼─┴─┴─┴─┴─┴─┤
│0 │16 │8 │3 │
├───────────┼───────────┼───────────┼───────────┤
BASE64 │A │Q │I │D │
└───────────┴───────────┴───────────┴───────────┘
需要注意的是,字节顺序是从低到高的,而二进制数位的顺序是从高到低的
字节数不是3的倍数
上面提到,假如要编码的二进制序列的字节数不是3的倍数,那么需要用字节0
将此序列补齐为3的倍数。
设序列长度为n,如果n % 3 == 1
,最后一组则只有一个字节,需要补充两个字节0
再转换。
这样,最后一组转换后的ASCII字符只有前两个是有效的,有效是指编码后的数据使用了二进制序列补充前的数据,在这也就是说余下的一个字节至少需要两个ASCII字符编码,后两个必为A -- 0
。为了表明后两个字节是补充的,需要将最后两个A
替换为=
。
同样的道理,如果n % 3 == 2
,需要将最后一个A
替换为=
比如,编码"\x01\x02\x03\x04"
BINARY \x01 \x02 \x03 \x04
\x01 \x02 \x03 \x04 0 0
BEFORE 00000001 00000010 00000011 00000100 00000000 00000000
AFTER 000000 010000 001000 000011 000001 000000 000000 000000
0 16 8 3 1 0 0 0
BASE64 A Q I D B A = =