目标
本章的目标是:
• | 创建一个通用加密库,以便使用 DES(数字加密标准)、三重 DES、Rijndeal 或 RC2 算法对数据进行加密和解密。 |
• | 在应用程序中使用加密库。 |
适用范围
本章适用于以下产品和技术:
• | Microsoft Windows® XP 或 Windows 2000 Server (Service Pack 3) 以及更高版本的操作系统 |
• | .NET Framework 版本 1.0 (Service Pack 2) 和更高版本 |
• | Microsoft Visual C#® .NET |
如何使用本章内容
本章详细介绍了使用 Visual C# 创建通用加密库的步骤及所需的代码。若要学好本章内容:
• | 您必须具有使用 Visual C# .NET 和 Microsoft Visual Studio® .NET 的经验。 |
• | 阅读如何在注册表中存储加密的连接字符串,以了解有关如何使用本章所介绍的库的示例。 |
摘要
Microsoft(r) .NET Framework 为各种最广泛使用的对称加密算法提供了支持。用于表示这些算法的类结构完善并提供了通用的使用模式。这意味着,您不必在每个应用程序中编写代码来对机密数据进行加密和解密,只需轻松创建一个可重复使用的库,就可以使用任何可用的对称加密算法来加密和解密数据。本章将介绍如何创建这类库。
创建 Visual C# 类库
此过程将创建 Visual C# 类库,以提供加密和解密功能。
• | 创建 Visual C# 类库
1. | 启动 Visual Studio .NET 并创建一个新的名为 Encryption 的 Visual C# 类库项目。 | 2. | 使用解决方案资源管理器将 class1.cs 重命名为 EncryptTransformer.cs。 | 3. | 在 EncryptTransformer.cs 中,将 Class1 重命名为 EncryptTransformer。 | 4. | 将该类的作用域由 public 更改为 internal。 internal class EncryptTransformer
| 5. | 在文件的顶部添加以下 using 语句。 using System.Security.Cryptography;
| 6. | 将以下枚举类型添加到 Encryption 命名空间中。 public enum EncryptionAlgorithm {Des = 1, Rc2, Rijndael, TripleDes};
| 7. | 将下面的私有成员变量添加到 EncryptTransformer 类中。 private EncryptionAlgorithm algorithmID;
private byte[] initVec;
private byte[] encKey;
| 8. | 用下面的构造函数替换默认构造函数。 internal EncryptTransformer(EncryptionAlgorithm algId)
{
//保存正在使用的算法。
algorithmID = algId;
}
| 9. | 将下面的方法添加到该类。 internal ICryptoTransform GetCryptoServiceProvider(byte[] bytesKey)
{
// 选取提供程序。
switch (algorithmID)
{
case EncryptionAlgorithm.Des:
{
DES des = new DESCryptoServiceProvider();
des.Mode = CipherMode.CBC;
// 查看是否提供了密钥
if (null == bytesKey)
{
encKey = des.Key;
}
else
{
des.Key = bytesKey;
encKey = des.Key;
}
// 查看客户端是否提供了初始化向量
if (null == initVec)
{ // 让算法创建一个
initVec = des.IV;
}
else
{ //不,将它提供给算法
des.IV = initVec;
}
return des.CreateEncryptor();
}
case EncryptionAlgorithm.TripleDes:
{
TripleDES des3 = new TripleDESCryptoServiceProvider();
des3.Mode = CipherMode.CBC;
// See if a key was provided
if (null == bytesKey)
{
encKey = des3.Key;
}
else
{
des3.Key = bytesKey;
encKey = des3.Key;
}
// 查看客户端是否提供了初始化向量
if (null == initVec)
{ //是,让算法创建一个
initVec = des3.IV;
}
else
{ //不,将它提供给算法。
des3.IV = initVec;
}
return des3.CreateEncryptor();
}
case EncryptionAlgorithm.Rc2:
{
RC2 rc2 = new RC2CryptoServiceProvider();
rc2.Mode = CipherMode.CBC;
// 测试是否提供了密钥
if (null == bytesKey)
{
encKey = rc2.Key;
}
else
{
rc2.Key = bytesKey;
encKey = rc2.Key;
}
// 查看客户端是否提供了初始化向量
if (null == initVec)
{ //是,让算法创建一个
initVec = rc2.IV;
}
else
{ //不,将它提供给算法。
rc2.IV = initVec;
}
return rc2.CreateEncryptor();
}
case EncryptionAlgorithm.Rijndael:
{
Rijndael rijndael = new RijndaelManaged();
rijndael.Mode = CipherMode.CBC;
// 测试是否提供了密钥
if(null == bytesKey)
{
encKey = rijndael.Key;
}
else
{
rijndael.Key = bytesKey;
encKey = rijndael.Key;
}
// 查看客户端是否提供了初始化向量
if(null == initVec)
{ //是,让算法创建一个
initVec = rijndael.IV;
}
else
{ //不,将它提供给算法。
rijndael.IV = initVec;
}
return rijndael.CreateEncryptor();
}
default:
{
throw new CryptographicException("算法 ID '" + algorithmID +
"' 不受支持。");
}
}
}
| 10. | 将下面的属性添加到该类。 internal byte[] IV
{
get{return initVec;}
set{initVec = value;}
}
internal byte[] Key
{
get{return encKey;}
}
| 11. | 将名为 DecryptTransformer 的新类添加到项目中。 | 12. | 在 DecryptTransformer.cs 文件的顶部添加以下 using 语句。 using System.Security.Cryptography;
| 13. | 将类作用域由 public 更改为 internal。 | 14. | 用下面的构造函数替换默认构造函数。 internal DecryptTransformer(EncryptionAlgorithm deCryptId)
{
algorithmID = deCryptId;
}
| 15. | 将下面的私有变量添加到该类。 private EncryptionAlgorithm algorithmID;
private byte[] initVec;
| 16. | 将下面的方法添加到该类。 internal ICryptoTransform GetCryptoServiceProvider(byte[] bytesKey)
{
// Pick the provider.
switch (algorithmID)
{
case EncryptionAlgorithm.Des:
{
DES des = new DESCryptoServiceProvider();
des.Mode = CipherMode.CBC;
des.Key = bytesKey;
des.IV = initVec;
return des.CreateDecryptor();
}
case EncryptionAlgorithm.TripleDes:
{
TripleDES des3 = new TripleDESCryptoServiceProvider();
des3.Mode = CipherMode.CBC;
return des3.CreateDecryptor(bytesKey, initVec);
}
case EncryptionAlgorithm.Rc2:
{
RC2 rc2 = new RC2CryptoServiceProvider();
rc2.Mode = CipherMode.CBC;
return rc2.CreateDecryptor(bytesKey, initVec);
}
case EncryptionAlgorithm.Rijndael:
{
Rijndael rijndael = new RijndaelManaged();
rijndael.Mode = CipherMode.CBC;
return rijndael.CreateDecryptor(bytesKey, initVec);
}
default:
{
throw new CryptographicException("算法 ID '" + algorithmID +
"' 不支持。");
}
}
} //end GetCryptoServiceProvider
| 17. | 将下面的属性添加到该类。 internal byte[] IV
{
set{initVec = value;}
}
| 18. | 将名为 Encryptor 的新类添加到项目中。 | 19. | 在 Encryptor.cs 的顶部添加以下 using 语句。 using System.Security.Cryptography;
using System.IO;
| 20. | 用下面的构造函数替换默认构造函数。 public Encryptor(EncryptionAlgorithm algId)
{
transformer = new EncryptTransformer(algId);
}
| 21. | 将下面的私有成员变量添加到该类。 private EncryptTransformer transformer;
private byte[] initVec;
private byte[] encKey;
| 22. | 将下面的 Encrypt 方法添加到该类。 public byte[] Encrypt(byte[] bytesData, byte[] bytesKey)
{
//设置将保存加密数据的流。
MemoryStream memStreamEncryptedData = new MemoryStream();
transformer.IV = initVec;
ICryptoTransform transform = transformer.GetCryptoServiceProvider
(bytesKey);
CryptoStream encStream = new CryptoStream(memStreamEncryptedData,
transform,
CryptoStreamMode.Write);
try
{
//加密数据,并将它们写入内存流。
encStream.Write(bytesData, 0, bytesData.Length);
}
catch(Exception ex)
{
throw new Exception("将加密数据写入流时
出错: /n"
+ ex.Message);
}
//为客户端进行检索设置初始化向量和密钥
encKey = transformer.Key;
initVec = transformer.IV;
encStream.FlushFinalBlock();
encStream.Close();
//发送回数据。
return memStreamEncryptedData.ToArray();
}//end Encrypt
| 23. | 将下面的属性添加到该类。 public byte[] IV
{
get{return initVec;}
set{initVec = value;}
}
public byte[] Key
{
get{return encKey;}
}
| 24. | 将名为 Decryptor 的新类添加到项目中。 | 25. | 在 Decryptor.cs 的顶部添加以下 using 语句 using System.Security.Cryptography;
using System.IO;
| 26. | 用下面的构造函数替换默认构造函数。 public Decryptor(EncryptionAlgorithm algId)
{
transformer = new DecryptTransformer(algId);
}
| 27. | 将下面的私有成员变量添加到该类。 private DecryptTransformer transformer;
private byte[] initVec;
| 28. | 将下面的 Decrypt 方法添加到该类。 public byte[] Decrypt(byte[] bytesData, byte[] bytesKey)
{
//为解密数据设置内存流。
MemoryStream memStreamDecryptedData = new MemoryStream();
//传递初始化向量。
transformer.IV = initVec;
ICryptoTransform transform = transformer.GetCryptoServiceProvider
(bytesKey);
CryptoStream decStream = new CryptoStream(memStreamDecryptedData,
transform,
CryptoStreamMode.Write);
try
{
decStream.Write(bytesData, 0, bytesData.Length);
}
catch(Exception ex)
{
throw new Exception("将加密数据写入流时
出错: /n"
+ ex.Message);
}
decStream.FlushFinalBlock();
decStream.Close();
// 发送回数据。
return memStreamDecryptedData.ToArray();
} //end Decrypt
| 29. | 将下面的属性添加到该类。 public byte[] IV
{
set{initVec = value;}
}
| 30. | 在“生成”菜单中,单击“生成解决方案”。 |
|
创建控制台测试应用程序
此过程创建一个简单的控制台测试应用程序以测试加密和解密功能。
• | 创建控制台测试应用程序
1. | 将一个新的名为 EncryptionTester 的 Visual C# 控制台应用程序添加到当前解决方案中。 | 2. | 在解决方案资源管理器中,右键单击 EncryptionTester 项目,然后单击“设为启动项目”。 | 3. | 使用解决方案资源管理器将 class1.cs 重命名为 EncryptionTest.cs。 | 4. | 在 EncryptionTest.cs 中,将 Class1 重命名为 EncryptionTest。 | 5. | 添加对 Encryption 项目的项目引用。 | 6. | 在 EncryptionTest.cs 的顶部添加以下 using 语句。 using System.Text;
using Encryption;
| 7. | 将以下代码添加到 Main 方法中。 // 设置需要的算法
EncryptionAlgorithm algorithm = EncryptionAlgorithm.Des;
// Init variables.
byte[] IV = null;
byte[] cipherText = null;
byte[] key = null;
try
{ //试图加密。
//创建 Encryptor。
Encryptor enc = new Encryptor(EncryptionAlgorithm.Des);
byte[] plainText = Encoding.ASCII.GetBytes("测试字符串");
if ((EncryptionAlgorithm.TripleDes == algorithm) ||
(EncryptionAlgorithm.Rijndael == algorithm))
{ //3Des 仅与 16 或 24 字节密钥一起使用。
key = Encoding.ASCII.GetBytes("password12345678");
if (EncryptionAlgorithm.Rijndael == algorithm)
{ // 对于 Rijndael,必须为 16 字节。
IV = Encoding.ASCII.GetBytes("init vec is big.");
}
else
{
IV = Encoding.ASCII.GetBytes("init vec");
}
}
else
{ //Des 仅使用 8 字节的密钥。其他使用长度可变的密钥。
//将密钥设置为空以生成一个新密钥。
key = Encoding.ASCII.GetBytes("password");
IV = Encoding.ASCII.GetBytes("init vec");
}
// 取消注释后面的行,为您生成密钥或初始化向量。
// key = null;
// IV = null;
enc.IV = IV;
// Perform the encryption.
cipherText = enc.Encrypt(plainText, key);
// 检索初始化向量和密钥。您将需要它
// 进行解密。
IV = enc.IV;
key = enc.Key;
// 查看您的加密文本和初始化向量。
Console.WriteLine(" 密码文本: " +
Convert.ToBase64String(cipherText));
Console.WriteLine("初始化向量: " + Convert.ToBase64
String(IV));
Console.WriteLine(" Key: " + Convert.ToBase64
String(key));
}
catch(Exception ex)
{
Console.WriteLine("加密时发生异常. " + ex.Message);
return;
}
try
{ //试图解密。
//设置您的解密,将它提供给算法和初始化
向量。
Decryptor dec = new Decryptor(algorithm);
dec.IV = IV;
// 继续并解密。
byte[] plainText = dec.Decrypt(cipherText, key);
// 查看您的纯文本。
Console.WriteLine(" 纯文本: " +
Encoding.ASCII.GetString(plainText));
}
catch(Exception ex)
{
Console.WriteLine("解密时发生异常。 " + ex.Message);
return;
}
| 8. | 在“生成”菜单中,单击“生成解决方案”。 | 9. | 运行测试应用程序以验证 Encryptor 和 Decryptor 类的操作。 |
|