本页内容
目标
本章的目标是:
| • | 在注册表中存储加密的数据库连接字符串 |
| • | 从注册表中读取加密的数据库连接字符串并对其进行解密。 |
适用范围
本章适用于以下产品和技术:
| • | Microsoft Windows XP 或 Windows 2000 Server (Service Pack 3) 以及更高版本的操作系统 |
| • | Microsoft .NET Framework 版本 1.0 (Service Pack 2) 以及更高版本 |
| • | Microsoft Visual C#® .NET |
如何使用本章内容
若要学好本章内容:
| • | 您必须具有使用 Visual C# .NET 进行编程的经验。 |
| • | 您必须具有使用 Microsoft Visual Studio® .NET 进行编程的经验。 |
| • | 您必须具有使用 ASP.NET 开发 Web 应用程序的经验。 |
| • | 按照如何创建加密库中所述创建常规加密库。此加密库所提供的功能在本章中用于为数据库连接字符串加密和解密。 |
| • | 请阅读第 12 章数据访问安全性中的安全存储数据库连接字符串。其中介绍了一些用于安全存储数据库连接字符串的技术。 |
摘要
如果开发人员所编写的应用程序需要访问数据库,那么他们都将面临一个相同的问题,即在哪个位置安全存储数据库连接字符串。注册表为他们提供了一种选择。不过,尽管使用访问控制列表 (ACL) 可保护单个注册表项的安全,但为了提高安全性,您应该先对连接字符串加密,然后才将其存储。
本章介绍如何将经过加密的数据库连接字符串存储在注册表中,以及如何从 ASP.NET Web 应用程序中检索它。它会用到您在如何创建加密库中创建的那个常规加密库。
您必须了解的背景知识
在开始学习本章之前,您应该知道:
| • | 用于加密的连接字符串、初始化向量和密钥将作为命名值存储在注册表中的以下注册表项下面。 HKEY_LOCAL_MACHINE/Software/TestApplication
|
| • | 必须存储初始化向量和密钥以便对连接字符串进行解密。 |
将加密数据存储在注册表中
此过程会创建一个 Windows 应用程序,用来为示例数据库字符串加密并将该字符串存储在注册表中。
| • | 在注册表中存储加密数据
| 1. | 启动 Visual Studio .NET,并创建一个新的名为 EncryptionTestApp 的 Visual C# 项目。 | | 2. | 添加对 Encryption.dll 程序集的引用。 要创建此程序集,必须执行本指南中如何创建加密库中所述的步骤。 | | 3. | 将下面的 using 语句添加到 Form1.cs 顶部现有 using 语句的下方。 using Encryption;
using System.Text;
using Microsoft.Win32;
| | 4. | 将表 1 中的控件加入 Form1,并如图 1 所示对它们进行排列。 表 1:EncryptionTestApp 控件
| 控件 | 文本 | ID | | 标签 | 连接字符串: | | | 文本框 | | txtConnectionString | | 标签 | 密钥: | | | 文本框 | | txtKey | | 标签 | 初始化向量: | | | 文本框 | | txtInitializationVector | | 标签 | 加密字符串 | | | 文本框 | | txtEncryptedString | | 标签 | 解密字符串 | | | 文本框 | | txtDecryptedString | | 按钮 | 加密 | btnEncrypt | | 按钮 | 解密 | btnDecrypt | | 按钮 | 写入注册表数据 | btnWriteRegistryData |
 图 1 “加密测试套”对话框 | | 5. | 将 txtConnectionString 的 Text 属性设置为 "Server=local; database=pubs; uid=Bob; pwd=Password"
| | 6. | 将 txtKey 的 Text 属性设置为 "0123456789012345"
密钥长度为 16 个字节以满足三重 DES 加密算法的要求。 | | 7. | 将 Form1 的 Text 属性设置为 "加密测试套"
| | 8. | 双击“加密”按钮以创建一个按钮单击事件处理程序,然后将以下代码添加到该事件处理程序中。 try
{
// 创建 Encryptor 对象,将 3DES 指定为
// 加密算法
Encryptor enc = new Encryptor(EncryptionAlgorithm.TripleDes);
// 以字节数组方式获取连接字符串
byte[] plainText = Encoding.ASCII.GetBytes(txtConnectionString.Text);
byte[] key = Encoding.ASCII.GetBytes(txtKey.Text);
// 执行加密
byte[] cipherText = enc.Encrypt(plainText, key);
// 存储初始化向量,解密需要
// 该向量
txtInitializationVector.Text = Encoding.ASCII.GetString(enc.IV);
// 显示加密字符串
txtEncryptedString.Text = Convert.ToBase64String(cipherText);
}
catch(Exception ex)
{
MessageBox.Show("加密时发生异常: " + ex.Message,
"加密测试套");
}
| | 9. | 在“设计器”模式下返回到 Form1,然后双击“解密”按钮以创建一个按钮单击事件处理程序。 | | 10. | 将下面的代码添加到“解密”按钮事件处理程序。 try
{
// 设置 Decryptor 对象
Decryptor dec = new Decryptor(EncryptionAlgorithm.TripleDes);
// 设置初始化向量
dec.IV = Encoding.ASCII.GetBytes(txtInitializationVector.Text);
byte[] key = Encoding.ASCII.GetBytes(txtKey.Text);
// 执行解密
byte[] plainText = dec.Decrypt(Convert.FromBase64String(
txtEncryptedString.Text),
key);
// 显示解密字符串。
txtDecryptedString.Text = Encoding.ASCII.GetString(plainText);
}
catch(Exception ex)
{
MessageBox.Show("解密时发生异常。 " + ex.Message,
"加密测试套");
}
| | 11. | 在“设计器”模式下返回到 Form1,然后双击“写入注册表数据”按钮以创建一个按钮单击事件处理程序。 | | 12. | 将下面的代码添加到该事件处理程序中。 // 创建注册表项和命名值
RegistryKey rk = Registry.LocalMachine.OpenSubKey("Software",true);
rk = rk.CreateSubKey("TestApplication");
// 将加密字符串、初始化向量和密钥写入注册表
rk.SetValue("connectionString",txtEncryptedString.Text);
rk.SetValue("initVector",Convert.ToBase64String(
Encoding.ASCII.GetBytes(txtInitializationVector.Text)));
rk.SetValue("key",Convert.ToBase64String(Encoding.ASCII.GetBytes(
txtKey.Text)));
MessageBox.Show("数据已成功写入注册表");
| | 13. | 运行该应用程序,然后单击“加密”。 在“加密字符串”字段中就会显示加密的连接字符串。 | | 14. | 单击“解密”。 在“解密字符串”字段中就会显示原始的字符串。 | | 15. | 单击“写入注册表数据”。 | | 16. | 在消息框中,单击“确定”。 | | 17. | 运行 regedit.exe 并查看以下注册表项的内容。 HKLM/Software/TestApplication
确认编码值是 connectionString、initVector 和 key 命名值的当前值。 | | 18. | 关闭 regedit 和测试套应用程序。 | |