本文继续Cryptography Application Block的学习,演示使用单向哈希算法(one-way hashing algorithm)加密存储在XML文件中的密码。本文由
http://blog.entlib.com 开源ASP.NET博客平台小组根据EntLib HOL手册编译提供,欢迎交流。
练习二:使用HashProvider
存储单向哈希密码
首先打开ex02\begin 目录下的UserUI.sln 项目文件,该应用程序提供了管理XML配置文件中的用户名和密码。
范例应用程序简要描述
1. 运行范例程序,输入用户名Elmo,并保持默认的密码(P@ssw0rd)不变,点击OK按钮。
添加一个新的用户Zoe,重复上面的步骤。点击Save按钮,将保存上述信息到UserStore.config文件中。
2. 关闭应用程序,在Visual Studio 中打开UserStore.config配置文件,你会发现password以明文的形式保存在配置文件中。
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
configuration
>
<
configSections
>
<
section
name
=
"userStore"type="UserStore.Configuration.UserSettings, UserStore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</
configSections
>
<
userStore
>
<
users
>
<
add
name
=
"EntLib.com"password="P@ssw0rd" />
<
add
name
=
"Forum"password="P@ssw0rd" />
</
users
>
</
userStore
>
</
configuration
>
使用前一节的对称加密密钥对密码进行加密并不是一个好的方法,因为会影响密码的安全性。一般采用单向哈希算法,在和已存储的哈希密码(一般存储在数据库中)进行比较之前,先对输入的密码进行哈希。在这种情况下,即使数据库泄漏,密码仍然是安全的。
在进行哈希算法之前,对密码添加额外的Salt,使得密码更难以破解。
配置Hash Provider
1. 使用Enterprise Library的配置管理工具打开项目中的app.config配置文件。配置文件已经定义了2个配置源(Configuration Source),应用程序使用Enterprise Library 中配置的封装类来管理UserStore.config的位置和内容,如下图所示。
2. 右键点击应用程序配置文件,选择New | Cryptography Application Block,为配置文件添加Cryptography application block的配置节点。
3. 选择Cryptography Application Block | Hash Providers 节点,添加 New | HashAlgorithm Provider,创建一个新的HashAlgorithm提供者。
4. 在弹出的Type Selector 对话框中,选择SHA1Managed类型,然后点击OK按钮。
对于哈希算法,推荐使用SHA256Managed算法,该使用使用256位的哈希大小,而SHA1Managed哈希算法是160位,该算法也可以接受。MD4和MD5算法则不再推荐使用。
5. 选择Cryptography Application Block | Hash Providers | SHA1Managed节点,设置如下属性:
Name = PasswordHasher
SaltEnabled = True
最后,保存好配置文件。
使用哈希算法
1. 选择Solution Provider中的UserStore项目,添加对Cryptography.dll程序集的引用。
Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.dll
2. 打开Security | HashHelper.cs文件(在UserStore项目中),添加如下命名空间的引用:
using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography;
3. 打开HashProvider类,添加如下代码:
class HashHelper
{
private HashHelper() { }
// TODO: Hash provider name must match app.config
private const string hashProvider = "PasswordHasher";
. . .
}
常量值必须匹配app.config配置文件中已命名的hash provider。
4. 修改CreateHash方法,如下所示。
public static string CreateHash(string plainText)
{
string hash = null;
// TODO: Hash the plain text
hash = Cryptographer.CreateHash(hashProvider, plainText);
return hash;
}
在内存中的敏感数据需要尽快清除。在内存中的未加密数据存在安全风险。需要了解的是在内存中的数据也有可能写到硬盘上,因此操作系统可能将数据写到交换文件上。此外,如果系统崩溃,操作系统也会将内存中的数据写到硬盘上。
5. 运行范例程序,重置Elmo的密码,点击Reset Password按钮,保留默认的密码(P@ssw0rd),然后点击OK按钮。UserStore.config配置文件中,当前明文保存的密码信息将替换为密码的哈希值。
6. 对用户Zoe也采用相同的步骤。
7. 点击Save按钮,保存对UserStore.config的修改。
8. 尝试更改Elmo的密码。点击Change Password按钮,输入默认的旧密码P@ssw0rd,然后数据新的密码,如EntLib,点击OK按钮。但是,此时会发生验证现有密码失败。为什么呢?看看后面的解释。
9. 点击Close按钮,关闭应用程序。
10. 在Visual Stuido中打开UserStore.config文件,发现密码都已经哈希了。
<?
xml
version
=
"1.0"encoding="utf-8"?>
<
configuration
>
<
configSections
>
<
section
name
=
"userStore"type="UserStore.Configuration.UserSettings, UserStore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</
configSections
>
<
userStore
>
<
users
>
<
add
name
=
"EntLib.com"password="3kHeDQo7uDI6Pj7890is1EiNGGjBB6ImxpB5LJkCFV+hY3Kp" />
<
add
name
=
"Forum"password="SBRc6JsFweEbxRfBStukevhur7RB3GpqaPLJRVymuK5WZ0e9" />
</
users
>
</
userStore
>
</
configuration
>
注意每种情况下,哈希值是不同的,即使实际的密码是相同的,这是因为额外的Salt。因此为了验证密码的有效性,我们不能简单应用对明文密码进行哈希计算,然后比较2个哈希字符串。
11. 打开Security | HashHelper.cs文件(在UserStore项目中),修改CompareHash方法中的如下代码。
public static bool CompareHash(string plainText, string hashedText)
{
bool compare = false;
compare = Cryptographer.CompareHash(hashProvider, plainText, hashedText);
return compare;
}
12. 再次运行应用程序,修改Elmo的密码 – 点击Change Password按钮,这次一定会成功。
参考文档:
Cryptography Application Block Hands-On Labs for Enterprise Library