俞志兵
南京市天印高级中学 南京 211151
作者:俞志兵,本科,中学一级教师,长期从事高中信息技术教学工作,任信息技术教研组组长,擅长网站开发。
总的来说,加密有两种形式:1)对称加密,加密和解密时使用的是同一个密钥;2)非对称加密,加密和解密时将使用不同的密钥。通常是用公钥作为加密密钥,任何人都可以用它来加密信息。私钥才是用来解密密钥的,它只能用来对使用其对应的公钥加密的数据进行解密。对称加密相对而言速度更快,但由于加密者和解密者都知道这个唯一的密钥,因此安全性更差一些。非对称加密则通过密钥的方法来解决这个问题,由于私钥永远不会暴露,所以第三方更加难以破解其加密的信息。由于密钥的方法需要更长的处理时间,因此通常的方法是使用非对称密钥加密机制在因特网上实现对对称密钥的加密,这样就使这个用于加密的密钥更安全,不会暴露给第三方。
在.NET的命名空间System.Security.Cryptography中提供了几种算法。可用的非对称算法包括DSA(Digital Signature Algorithm,数字签名算法)和RSA(Rivest-Shamir-Adleman算法,它由3个发明者的名字组成:Ronald Rivest、Adi Shamir和Leonard Adleman)两种。其中DSA只能够用来对数据进行“签名”,因此通常用来做验证,而RSA更加通用。DSA现在是美国政府使用的数字验证的标准。
.NET框架中可以找到的对称加密算法包括DES(Data Encryption Standard,数字加密标准)、Triple DES(3DES)、RC2(Ron’s Code或Rivest’s Cipher,都是源于Ronald Rivest)和Rijndael(源于其发明者John Daemem、Vincent Rijman的名字)。DES成为标准已经有一段时间,尽管它也不断发生变化。3DES和RC2都是DES的变种。3DES是通过对数据进行3次独立的DES加密,扣除奇偶校验位,其总的密钥长度也达到168位。RC2的密钥长度是可以变化的,最大可以达到128(如果要更长的密钥,可以使用RC3、RC4等),因此根据密钥长度不同,可能比DES更脆弱或更强壮。Rijndael是一种完全不同的加密方法,现在已经被接纳为新的AES(高级加密标准)。该标准的目标是替代DES。
由于.NET框架中的类是针对数据流进行优化的,因此需要花一些时间来处理数据格式转换。同样需要定义一个密钥以及执行加密或解密操作的初始向量(IV)。需要使用IV应归究于加密的本性:为一串数据位计算加密值时,将会用到前面一串数据位的加密值。由于在加密开始时并不存在这些值,因此用IV来代替。在实践中,IV和密钥都将表示为一个字节的数组,而在DES加密中,其长度是64位(8字节),由于解密算法与加密算法类似,加密需要写入加密数据的目标数据流,而解密需要一个从中读取已加密数据的源数据流。
对一个字符串进行加密所需的步骤:将源字符串转换为一个字节数组;初始化一个加密算法类;使用这个加密算法类来生成一个加密者(encryptor)对象,实现Icrypto-Transform接口,它需要密钥和IV值;使用加密者对象来初始化一个密文数据流(CryptoStream对象),该数据流还需要知道要加密哪些数据,以及用来写入加密数据的目标数据流;使用这个密文数据流生成已加密数据,并写到由前面创建的源字节数组创建的目标内存数据流中;获取存储在这个数据流中的字节数据;将这些字节数据转换成一个字符串。
解密所采用的模式与加密类似:将源字符串转换成一个字节数组;根据这个字节数组填充内存数据流的值;初始化一个加密算法类;使用加密算法类生成一个解密者(decryptor)对象,实现ICryptoTransform接口,它需要密钥和IV值;使用解密者对象来初始化一个密文数据流(ICryptoStream)对象,该数据流还需要知道解密什么数据,并需要一个从中读取已加密数据的源数据流;使用密文数据流来读取已经解密数据(可以使用StreamReader.ReadToEnd方法来获取字符串型结果)。
限于篇幅,本文只给出加密方法,读者可以根据加密方法自己写出解密方法。
在网站根目录下,新建文件夹(SecurityLib),在这个文件夹中新建类,命名为StringEncryptor。其Encrypt()方法如下所示:
public static string Encrypt(string sourceData)
{
set key and initialization vector values
byte[] key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
byte[] iv = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
try
{ convert data to byte array
byte[] sourceDataBytes =
System.Text.ASCIIEncoding.ASCII.GetBytes(sourceData);
get target memory stream
MemoryStream tempStream = new MemoryStream();
get encryptor and encryption stream
DESCryptoServiceProvider encryptor =
new DESCryptoServiceProvider();
CryptoStream encryptionStream =
new CryptoStream(tempStream,
encryptor.CreateEncryptor(key, iv),
CryptoStreamMode.Write);
encrypt data
encryptionStream.Write(sourceDataBytes, 0,
sourceDataBytes.Length);
encryptionStream.FlushFinalBlock();
put data into byte array
byte[] encryptedDataBytes = tempStream.GetBuffer();
convert encrypted data into string
return Convert.ToBase64String(encryptedDataBytes, 0,(int)tempStream.Length);
}
}
1)网站根目录下新建Web页面,命名为SecurityTest.asp,做如下编辑:
Enter data to encrypt:
Enter data to decrypt:
2)修改SecurityTest.aspx.cs中的代码:
using System;
…
using System.Text;
using SecurityLib;
…
protected void processButton_Click(object sender, EventArgs e)
{
string stringToEncrypt = encryptBox.Text;
string stringToDecrypt = decryptBox.Text;
string encryptedString =
StringEncryptor.Encrypt(stringToEncrypt);
if (stringToDecrypt == "")
{
stringToDecrypt = encryptedString;
}
string decryptedString =
StringEncryptor.Decrypt(stringToDecrypt);
StringBuilder sb = new StringBuilder();
sb.Append(“Encrypted data: “);
sb.Append(encryptedString);
sb.Append(“
Decrypted data: “);
sb.Append(decryptedString);
result.Text = sb.ToString();
}
3)在浏览器中运行SecurityTest.aspx,在第一个要加密的文本框中输入“i am yuzhibing”,然后点击Process按钮,其结果如图1所示。
现在绝大部分电子商务网站或平台,都需要用户档案系统,需要用户编辑客户详情,包括信用卡详情。信用卡中的信息出于安全因素考虑,必须加密后保存到数据层的数据库中。登录客户编辑自己的信息,就需要从数据库中解密到表示层。
[1]郑齐心,房大伟,刘云峰.ASP.NET项目开发案例全程实录[M].2版.北京:清华大学出版社,2011.
[2]赵松涛,陈小龙.Visual Studio 2005+SQL Server2005数据库应用系统开发[M].北京:电子工业出版社,2007.
[3]Darie C, Watson K. ASP.NET 2.0电子商务开发实战[M].北京:人民邮电出版社,2007.