将密码格式从加密密码更改为散列密码
我发现令人惊讶的是,将现有数据库从加密密码密码转换为散列密码的信息很少。 (我能够找到更多有关转换另一种方式的信息,但这并没有多大帮助。)将密码格式从加密密码更改为散列密码
正如大多数人所知,更改web.config中的passwordFormat
设置仅影响新用户。我有一个数百个用户的数据库,我想将它们转换为使用哈希密码而不更改这些现有密码。
是否有人熟悉如何接近这个?感谢您的任何提示。
这是我与我怎么看远了启动方法:
- 在我的web.config创建两个MembershipProviders,一个用于加密密码和一个用于散列。
- 使用加密密码提供程序遍历所有用户。 (SqlMembershipProvider.GetAllUsers)
- 使用加密密码提供程序获取用户密码。 (MembershipUser.GetPassword)
- 使用哈希密码提供程序将用户密码更改为相同密码。 (MembershipUser.ChangePassword)
所以它会是这样的:
<membership defaultProvider="HashedProvider">
<providers>
<clear />
<add name="HashedProvider" connectionStringName="MembershipConnectionString" enablePasswordRetrieval="false" requiresQuestionAndAnswer="false" applicationName="MyApp" passwordFormat="Hashed" type="System.Web.Security.SqlMembershipProvider" />
<add name="EncryptedProvider" connectionStringName="MembershipConnectionString" enablePasswordRetrieval="true" requiresQuestionAndAnswer="false" applicationName="MyApp" passwordFormat="Encrypted" type="System.Web.Security.SqlMembershipProvider" />
</providers>
</membership>
代码:
SqlMembershipProvider hashedProvider = (SqlMembershipProvider)Membership.Providers["HashedProvider"];
SqlMembershipProvider encryptedProvider = (SqlMembershipProvider)Membership.Providers["EncryptedProvider"];
int unimportant;
foreach (MembershipUser user in encryptedProvider.GetAllUsers(0, Int32.MaxValue, out unimportant))
{
hashedProvider.ChangePassword(user.UserName, user.GetPassword(), user.GetPassword());
}
我会告诫你不要随意散列你的密码,因为这种方法有很多警告。这Blog post about hashing passwords是非常有见识的,我认为你应该阅读它。为什么你想要散列密码而不是加密?
感谢您的链接,这是一个有趣的阅读。也就是说,没有任何方法是100%安全的,哈希密码是当前密码存储的行业标准。为了方便用户使用加密密码(我可以通过电子邮件发送给他们),我建立了自己的网站,但是我收到了抱怨,这给我的用户带来了风险,尤其是当他们在多个网站上使用相同的密码时。 – 2011-02-09 18:41:30
出于安全原因,从数据库中的加密密码切换到散列绝对是正确的决定。
一般创建哈希出你现有的加密密码,你应该首先对它们进行解密,然后散列它们。请注意,您将会丢失(当您最终切换时)原始密码。相反,您将拥有用户密码的唯一指纹(散列)。
还考虑使用盐的散列(防御rainbow tables等),也有慢的哈希算法出于安全考虑,而不是快速的像MD5一个样子BCrypt(Codeplex & Article: How To Safely Store A Password)。
请记住,在未来将切换哈希算法比将其从ecryption更改为哈希更加费力。所以,你想这样做正确的第一次;)
是的,我明白什么是散列密码,以及如何不能从散列转换为原始密码。而且我知道我需要解密已加密的密码,然后对它们进行哈希处理。我不知道的是,我可以如何以一种能够与ASP.NET成员身份协同工作的方式来处理所有记录。 (顺便说一下,ASP.NET成员资格中没有使用散列密码的盐吗?) – 2011-02-09 18:43:33
ASP.NET成员资格的默认散列算法是SHA1,它们使用编码为Base64的salt。 – 2011-02-09 18:48:52
格雷格的解决方案是一个良好的开端,但它不会影响现有的用户。 SqlMembershipProvider通过在表中存储PasswordFormat(0 = clear,1 = Hashed,2 = Encrypted)和密码来保护现有的用户和密码。更改提供程序密码格式只影响对用户表的插入。为了将现有用户的密码转换为哈希,您必须更改每个条目的PasswordFormat参数。这是一个简单的方法来做到这一点:
void HashAllPasswords()
{
var clearProvider = Membership.Providers["SqlProvider_Clear"];
var hashedProvider = Membership.Providers["SqlProvider_Hashed"];
int dontCare;
if (clearProvider == null || hashedProvider == null) return;
var passwords = clearProvider.GetAllUsers(0, int.MaxValue, out dontCare)
.Cast<MembershipUser>().ToDictionary(u => u.UserName, u => u.GetPassword());
using (var conn = new SqlConnection(
ConfigurationManager.ConnectionStrings[0].ConnectionString))
{
conn.Open();
using (var cmd = new SqlCommand(
"UPDATE [aspnet_Membership] SET [PasswordFormat]=1", conn))
cmd.ExecuteNonQuery();
}
foreach (var entry in passwords)
{
var resetPassword = hashedProvider.ResetPassword(entry.Key, null);
hashedProvider.ChangePassword(entry.Key, resetPassword, entry.Value);
}
}
我正在尝试将明文密码更新为加密密码。我希望他们哈希,但客户端没有。总之,这个解决方案看起来很有前途非常优雅的简单。希望它有效。 – mikesigs 2011-02-10 15:36:19