编码和加密
很多人都以为编码(Encoding)和加密(Encryption)是同一个意思。编码和加密都是对格式的一种转换,但是它们是有区别的。编码是公开的,比如下面要介绍的Base64编码,任何人都可以解码;而加密则相反,你只希望自己或者特定的人才可以对内容进行解密。
BASE64编码的目的
由于某些系统中只能使用ASCII字符,Base64编码就是用来将非ASCII字符的数据转换成ASCII字符的一种方法。而且base64特别适合在http,mime协议下快速传输数据。base64其实不是安全领域下的加密解密算法。虽然有时候经常看到所谓的base64加密解密。其实base64只能算是一个编码算法,对数据内容进行编码来适合传输。在网络传输、邮件等系统中,BASE64的编码方式被广泛的应用。
BASE64编码的范围
X.509公钥证书也好,电子邮件数据也好,经常要用到Base64编码,那么为什么要作一下这样的编码呢?
我们知道任何计算机都支持按ascii码方式存储的数据,但ascii码的128~255之间的值是不可见字符,在不同的设备上处理方式可能会不同。在网络上交换数据时,比如说从A地传到B地,往往要经过多个路由设备,由于不同的设备对不可见字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这是不利于传输的。所以就先把源数据先做一个Base64编码,统统变成可见字符,这样出错的可能性就大降低了。
对证书来说,特别是根证书,一般都是作Base64编码的,因为它要在网上被许多人下载。电子邮件的附件一般也作Base64编码的,因为一个附件数据往往是有不可见字符的。
那么Base64到底是怎样编码的呢?
简单来说,任何一个数据无非可以看作一个比特流,那么我们取6个比特为一组,计算它的ascii值,得到一个字符,这个字符肯定是可见字符,好,把它对应的字符写出来,再取6个比特,计算...,如此下去,直到最后,就完成了编码。
base64范围如下:
0-9
a-z
A-Z
+
/
=
所以base64字符串里面一共有:
64种普通字符和1种补位字符,=就是那个补位字符。
base64是把每3个字节数据变成4个可打印字符,如果原数据长度不能被3整除,base64要在后面添加\0凑齐。
凑齐之后的数据的字节长度一定是3N,经过base64编码之后可打印出来4N个字符。
所以base64编码后的字符串一定能被4整除,并且在字符串的末尾可能出现1个或者2个等号,这是因为如果原文长度不能被3整除,base64要在后面添加\0凑齐。添加了几个字节的\0就会base64编码成几个等号。
BASE64编码的实现
BASE64的算法十分简单。
首先,BASE64把数据流的所有bit分开;
然后,按照每6位bit组成一个字节,
最后,在每个新字节的高位添加两个0进行补位,组成新的字节数组。
例如,一个字节数组包含3个字节,BASE64编码时将把其分配到4个新的字节中(3*8/6=4),其中每个字节只填充低6位,最后把高2位置0。
下图说明了BASE64的算法:
BASE64编码在.Net中的实现
在C#中通常使用Convert类型来进行BASE64编码和解码,它可以进行8位的字节数组和BASE64编码的字符串的转换。以下代码展示了其用法。
static void Main()
{
string str = "abcde";
//Generate UTF8 byte array
byte[] bytes = Encoding.UTF8.GetBytes(str);
//Converted into Base64 string
string base64 = BytesToBase64(bytes);
Console.WriteLine(base64);
//Back to UTF8 byte array.
bytes = Base64ToBytes(base64);
//Back to string.
Console.WriteLine(Encoding.UTF8.GetString(bytes));
Console.Read();
}
//Converts 8-bit byte array into Base64 string
static string BytesToBase64(byte[] bytes)
{
try
{
//Conversion is not successful will throw an exception
return Convert.ToBase64String(bytes);
}
catch (Exception)
{
return null;
}
}
//Converts Base64 string into 8-bit byte array
static byte[] Base64ToBytes(string base64)
{
try
{
//Conversion is not successful will throw an exception
return Convert.FromBase64String(base64);
}
catch (Exception)
{
return null;
}
}
如以上代码所示,Convert类型提供了非常简单的接口以支持BASE64字符串和字节数组之间的转换.
但需要注意的是,Convert类型在转换失败时将直接抛出异常,在任何时刻都必须把Convert类型的操作语句放在try、catch块中。
下面是以上代码的执行结果: