在看HTTP基本认证的时候了解了一下Base64,在这里简单的写一下。

Base64应用

先来说一下都哪些地方有Base64的身影吧。迅雷大家都比较熟悉,它的专用链接以thunder://开头,后面的一串地址则是经过Base64编码的。开头说了HTTP基本认证,它则是将"用户名:密码"经过Base64编码附加到HTTP请求头中的。还有Data URI scheme以及ASP.NET WEB FORM那令人讨厌的ViewState隐藏字段等。当然最常用的还是Email,相关内容可参考这里。举个例子,在126邮箱中,找一封邮件,选择“查看信头”,如下图所示:

浅谈Base64-程序旅途

结果如下图所示:

浅谈Base64-程序旅途

从上图可以看到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基本认证。