在看HTTP基本认证的时候了解了一下Base64,在这里简单的写一下。
Base64应用
先来说一下都哪些地方有Base64的身影吧。迅雷大家都比较熟悉,它的专用链接以thunder://开头,后面的一串地址则是经过Base64编码的。开头说了HTTP基本认证,它则是将"用户名:密码"经过Base64编码附加到HTTP请求头中的。还有Data URI scheme以及ASP.NET WEB FORM那令人讨厌的ViewState隐藏字段等。当然最常用的还是Email,相关内容可参考这里。举个例子,在126邮箱中,找一封邮件,选择“查看信头”,如下图所示:
结果如下图所示:
从上图可以看到Content-Type:text/html; charset=utf-8 , Content-Transfer-Encoding:base64,当然也有的邮件Content-Transfer-Encoding为quoted-printable,如果是一个multi-part的邮件,可能每一部分都不一样,这里面涉及的东西比较多,有兴趣的可以参考相关文章。
那么为什么要用Base64编码呢?维基百科中解释说Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据。包括MIME的email、在XML中存储复杂数据。比如可以使用Base64编码传输Blob数据,还可以将二进数据存进文本文件,总之二进制文件办不到的事情就让Base64出马吧。
Base64编码
下面来揭开Base64的真面目。ASCII码大家应该都比较熟悉了,Base64就是从ASCII码(确切的说是ASCII打印字符)中选择64个字符作为一个基本字符集,然后,其他所有的不管是字符,图片等都可以转换成这64个字符的表示形式。比如柠檬树博客编码为Base64的形式为5p+g5qqs5qCR5Y2a5a6i,准确的说是柠檬树博客的UTF-8编码对应的Base64是这个,柠檬树博客的GB2312编码对应的Base64则是xPvDysr3sqm/zQ==。Base64中的64个字符分别为小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/",另外还有一个填补用的"="。下面的表格是Base64转换对照表:
0 A 12 M 24 Y 36 k 48 w 60 8 1 B 13 N 25 Z 37 l 49 x 61 9 2 C 14 O 26 a 38 m 50 y 62 + 3 D 15 P 27 b 39 n 51 z 63 / 4 E 16 Q 28 c 40 o 52 0 5 F 17 R 29 d 41 p 53 1 6 G 18 S 30 e 42 q 54 2 7 H 19 T 31 f 43 r 55 3 8 I 20 U 32 g 44 s 56 4 9 J 21 V 33 h 45 t 57 5 10 K 22 W 34 i 46 u 58 6 11 L 23 X 35 j 47 v 59 7
Base64的转换非常简单,就是每3个字节转换成4个字节,不足3个字节则用"="填补。每个byte是8bit,3个字节转换成4个字节的话,每个字节分得6bit,不足8bit,需要在高位补00。下面以一个实际的例子演示一下编码的过程:
文本 | M | a | n | |||||||||||||||||||||
ASCII | 77 | 97 | 110 | |||||||||||||||||||||
二进制 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 |
索引 | 19 | 22 | 5 | 46 | ||||||||||||||||||||
Base64编码 | T | W | F | u |
这个例子正好是3个字节,首先M a n对应的ASCII码十进制为77,97,110,对应的二进制为01001101,01100001,01101110,将这24个bit分成4组,每组6个bit,每组在高位再分别补两个0凑够8bit,分别为00010011,00010110,00000101,00101110,这四组二进制分别对应的十进制为19,22,5,46,查找Base64转换对照表,可以得到Man的Base64编码为TWFu。
下面再说一下不足3字节的情况,分别是2字节情况和1字节情况。下面还是举例说明:
2字节情况:
文本 | M | a | ||||||||||||||||||||||
ASCII | 77 | 97 | ||||||||||||||||||||||
二进制 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | x | x | x | x | x | x | ||
二进制(补0) | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | x | x | x | x | x | x |
索引 | 19 | 22 | 4 | |||||||||||||||||||||
Base64编码 | T | W | E | = |
M a两个字符二进制只有16bit,将这16bit分成3组,前2组各6bit,最后一组还剩4bit,这样最后一组需要在低位补两个0,然后在每一组的高位各补两个0,这3组二进制对应的十进制为19,22,4,查找Base64转换对照表,分别为T,W,E,再在最后补一个“=”,最后Ma的Base64编码为TWE=。
1字节情况:
文本 | M | |||||||||||||||||||||||
ASCII | 77 | |||||||||||||||||||||||
二进制 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | x | x | x | x | x | x | x | x | x | x | x | x | ||||
二进制(补0) | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | x | x | x | x | x | x | x | x | x | x | x | x |
索引 | 19 | 16 | ||||||||||||||||||||||
Base64编码 | T | Q | = | = |
M只有8bit,需要分成2组,第一组6bit,第二组2bit,第二组不足6bit,需要在低位补四个0,然后在两组的高位各补两个0,这2组二进制对应的十进制为19,16,查找Base64转换对照表,分别为T,Q,再在最后补两个“=”,最后M的Base64编码为TQ==。
上面举的例子都是英文字符,那么Base64怎么编码中文呢?因为中文有多种编码,比如GB2312,GBK,UTF-8等,比如“田”的GB2312编码为“CCEF”,UTF-8编码为“E794B0”。下面以UTF-8为例:
文本 | 田 | |||||||||||||||||||||||
十六进制 | E7 | 94 | B0 | |||||||||||||||||||||
二进制 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
索引 | 57 | 57 | 18 | 48 | ||||||||||||||||||||
Base64编码 | 5 | 5 | S | w |
C#中的Base64
C#提供了Base64编码和解码的类,这里我就不详细叙述了,直接贴出简单的程序:
static void Main(string[] args) { //Base64编码 var toBytes = System.Text.Encoding.UTF8.GetBytes("田"); var base64 = Convert.ToBase64String(toBytes); Console.WriteLine(base64); var toBytes1 = System.Text.UTF8Encoding.UTF8.GetBytes("田"); var base641 = Convert.ToBase64String(toBytes1); Console.WriteLine(base641); /*---------------------------------------------------*/ //Base64解码 var fromBtyes2 = Convert.FromBase64String("55Sw"); var text = System.Text.Encoding.UTF8.GetString(fromBtyes2); Console.WriteLine(text); }
关于Base64就写这些吧,接下来写一下Http基本认证。
好文。
写的不错w