看图解http时看到首部字段Content-MD5,说先根据报文主体执行MD5编码,得到的二进制数在用Base64编码,最终得到一串字符,用于对报文主体的准确性校验。这MD5是什么?Base64又是什么?抱着这些疑问,花了半天整理了一下编码相关的基础知识,最后通过练习,最后初步了解为什么要编码,这些编码到底是怎么计算运行的。
ASCII
用8bit表示字符的编码格式,256个可用字符,128个已定义字符,其中33个控制字符(已陈废),95个可显字符。
ASCII码表
二进制 | 十进制 | 十六进制 | 图形 | 二进制 | 十进制 | 十六进制 | 图形 | 二进制 | 十进制 | 十六进制 | 图形 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0010 0000 | 32 | 20 | (space) | 0100 0000 | 64 | 40 | @ | 0110 0000 | 96 | 60 | ` | |
0010 0001 | 33 | 21 | ! | 0100 0001 | 65 | 41 | A | 0110 0001 | 97 | 61 | a | |
0010 0010 | 34 | 22 | " | 0100 0010 | 66 | 42 | B | 0110 0010 | 98 | 62 | b | |
0010 0011 | 35 | 23 | # | 0100 0011 | 67 | 43 | C | 0110 0011 | 99 | 63 | c | |
0010 0100 | 36 | 24 | $ | 0100 0100 | 68 | 44 | D | 0110 0100 | 100 | 64 | d | |
0010 0101 | 37 | 25 | % | 0100 0101 | 69 | 45 | E | 0110 0101 | 101 | 65 | e | |
0010 0110 | 38 | 26 | & | 0100 0110 | 70 | 46 | F | 0110 0110 | 102 | 66 | f | |
0010 0111 | 39 | 27 | ' | 0100 0111 | 71 | 47 | G | 0110 0111 | 103 | 67 | g | |
0010 1000 | 40 | 28 | ( | 0100 1000 | 72 | 48 | H | 0110 1000 | 104 | 68 | h | |
0010 1001 | 41 | 29 | ) | 0100 1001 | 73 | 49 | I | 0110 1001 | 105 | 69 | i | |
0010 1010 | 42 | 2A | * | 0100 1010 | 74 | 4A | J | 0110 1010 | 106 | 6A | j | |
0010 1011 | 43 | 2B | + | 0100 1011 | 75 | 4B | K | 0110 1011 | 107 | 6B | k | |
0010 1100 | 44 | 2C | , | 0100 1100 | 76 | 4C | L | 0110 1100 | 108 | 6C | l | |
0010 1101 | 45 | 2D | - | 0100 1101 | 77 | 4D | M | 0110 1101 | 109 | 6D | m | |
0010 1110 | 46 | 2E | . | 0100 1110 | 78 | 4E | N | 0110 1110 | 110 | 6E | n | |
0010 1111 | 47 | 2F | / | 0100 1111 | 79 | 4F | O | 0110 1111 | 111 | 6F | o | |
0011 0000 | 48 | 30 | 0 | 0101 0000 | 80 | 50 | P | 0111 0000 | 112 | 70 | p | |
0011 0001 | 49 | 31 | 1 | 0101 0001 | 81 | 51 | Q | 0111 0001 | 113 | 71 | q | |
0011 0010 | 50 | 32 | 2 | 0101 0010 | 82 | 52 | R | 0111 0010 | 114 | 72 | r | |
0011 0011 | 51 | 33 | 3 | 0101 0011 | 83 | 53 | S | 0111 0011 | 115 | 73 | s | |
0011 0100 | 52 | 34 | 4 | 0101 0100 | 84 | 54 | T | 0111 0100 | 116 | 74 | t | |
0011 0101 | 53 | 35 | 5 | 0101 0101 | 85 | 55 | U | 0111 0101 | 117 | 75 | u | |
0011 0110 | 54 | 36 | 6 | 0101 0110 | 86 | 56 | V | 0111 0110 | 118 | 76 | v | |
0011 0111 | 55 | 37 | 7 | 0101 0111 | 87 | 57 | W | 0111 0111 | 119 | 77 | w | |
0011 1000 | 56 | 38 | 8 | 0101 1000 | 88 | 58 | X | 0111 1000 | 120 | 78 | x | |
0011 1001 | 57 | 39 | 9 | 0101 1001 | 89 | 59 | Y | 0111 1001 | 121 | 79 | y | |
0011 1010 | 58 | 3A | : | 0101 1010 | 90 | 5A | Z | 0111 1010 | 122 | 7A | z | |
0011 1011 | 59 | 3B | ; | 0101 1011 | 91 | 5B | [ | 0111 1011 | 123 | 7B | { | |
0011 1100 | 60 | 3C | < | 0101 1100 | 92 | 5C | \ | 0111 1100 | 124 | 7C | ||
0011 1101 | 61 | 3D | = | 0101 1101 | 93 | 5D | ] | 0111 1101 | 125 | 7D | } | |
0011 1110 | 62 | 3E | > | 0101 1110 | 94 | 5E | ^ | 0111 1110 | 126 | 7E | ~ | |
0011 1111 | 63 | 3F | ? | 0101 1111 | 95 | 5F | _ |
UNICODE
Unicode只是一个字符集,只规定了符号的二进制代码,但不规定这个二进制代码如何存储。实际字符与二进制代码转换时还需要用到具体转换格式,如UTF-8,UTF-16等。
BigEndian & LittleEndian
ANSI、UTF-16会区分big endian和little endian。
当用两个字节表示一个符号时,从第一个字节往后编码和解析的方式为Big Endian大头方式,从最后一个字节往前编码和解析的方式为LittleEndian小头方式。
Unicode规范中定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。这正好是两个字节,而且FF比FE大1。
如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。
UTF-8
unicode的字符集庞大,一个字符长度可能是三个字节(24bit)甚至4个字节(32bit)。固定长度的编码方式容易造成资源极大浪费(UTF-16用两个或4个字节,UTF-32固定4个字节)。
基于unicode的一种变长的编码方式,可用1~4个字节表示单个符号。
UTF-8的编码规则:
对于单字节字符,字节第一位设为0,后面7位为这个符号的unicode码。因此对于英文字母和数字,UTF-8编码和ASCII编码是相同的。
对于n个字节的字符(n>1),第一个字节的前n位设为1,第n+1位设为0;后面字节的前两位设为10;剩下空余字节全部为这个符号的unicode码。
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制) |
---|---|
0000 0000-0000 007F | 0xxxxxxx |
0000 0080-0000 07FF | 110xxxxx 10xxxxxx |
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
UTF-8最大容量10FFFF,即1,114,111个字符。例子:
“严”对应unicode为4E25(100111000100101),判断占用三个字节,即格式为1110xxxx 10xxxxxx 10xxxxxx,然后从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出位数补0,即得到了“严”的UTF-8编码:11100100 10111000 10100101,转换成十六进制就是E4B8A5。
BASE64
Base64是基于64个可打印字符来表示二进制数据的表示方法。2的6次方为64,所以每6bits为一个单元,对应某个可打印字符。
64个字符包含a-zA-Z0-9功62个字符,以及加号“+”和斜杠“/”。等号“=”作为后缀补位符(不在64个字符之内)。
Base64索引
数值 | 字符 | 数值 | 字符 | 数值 | 字符 | 数值 | 字符 |
---|---|---|---|---|---|---|---|
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 | / |
如果被编码的字节数不能被3整除,最后会多出1个或2个单位,先用0在末尾补足使其能够被3整除,然后再进行Base64编码。编码完成后的Base64文本后加上一个或两个等号“=”,代表补足的单位数。
MD5
Message-Digest Algorithm(消息摘要算法)简称MD5,一种被广泛使用的密码散列函数。输入不定长度信息,经过程序流程,生成四个32位数据,最后合在一起生成一个128位散列。
SHA
Secure Hash Algorithm(安全散列算法)缩写SHA,是一个密码散列函数家族。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。
最后回到Content-MD5
HTTP中Content-MD5即一串由MD5算法生成的值,其目的在于检查报文主体在传输过程中是否保持完整,以确认消息传输到达。对报文主体执行MD5算法获得128位二进制数后,HTTP首部无法记录二进制值,所以还要通过Base64编码处理。例:
对”blog”做MD5编码结果:126AC9F6149081EB0E97C2E939EAAD52,再对MD5码的二进制做Base64编码:
MD5(三位) | 二进制数 | Base64对二进制数分割 | Base64码 |
---|---|---|---|
12 6A C9 | 0001 0010 0110 1010 1100 1001 | 000100 100110 101011 001001 | EmrJ |
F6 14 90 | 1111 0110 0001 0100 1001 0000 | 111101 100001 010010 010000 | 9hSQ |
... | ... | ... | ... |
52 | 0101 0010 | 010100 100000 | Ug== |
最终Base64编码即 EmrJ9hSQgesOl8LpOeqtUg==
编码相关文章参考:http://www.ruanyifeng.com/blo...阮大师07年写了一篇通俗易懂的关于ASCII,unicode和utf-8的文章,至今都还有人在留言,拜服。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。