将密码格式从加密更改为散列

发布于 2024-10-16 13:14:53 字数 220 浏览 7 评论 0原文

我发现有关将现有数据库从加密密码转换为哈希密码的信息少之又少。 (我能够找到更多有关以其他方式转换的信息,但这没有多大帮助。)

正如大多数人所知,更改 web.config 中的 passwordFormat 设置只会影响新用户。我有一个包含数百个用户的数据库,我想将它们转换为使用散列密码,而不更改这些现有密码。

还有其他人熟悉如何解决这个问题吗?感谢您的任何提示。

I'm finding surprisingly little information on converting an existing database from Encrypted passwords to Hashed passwords. (I was able to find a bit more information on converting the other way, but it wasn't of much help.)

As most people know, changing the passwordFormat setting in web.config only affects new users. I have a database with a couple of hundred users and I'd like to convert them to use hashed passwords without changing those existing passwords.

Is anyone else familiar with how one might approach this? Thanks for any tips.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

只等公子 2024-10-23 13:14:53

Greg 的解决方案是一个好的开始,但不会影响现有用户。 SqlMembershipProvider 通过将PasswordFormat(0=明文、1=散列、2=加密)与密码一起存储在表中来保护现有用户和密码。更改提供者密码格式仅影响对用户表的插入。为了将现有用户的密码转换为散列密码,您必须更改每个条目的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);
    }
}

Greg's solution is a good start, but it won't affect existing users. The SqlMembershipProvider protects existing users and passwords by storing the PasswordFormat (0=clear, 1=Hashed, 2=Encrypted) in the table along with passwords. Changing the provider password format only affects inserts to the user tables. In order to convert existing users' passwords to Hashed, you have to change the PasswordFormat parameter for each entry. Here is a simple way to do this:

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);
    }
}
上课铃就是安魂曲 2024-10-23 13:14:53

这是我开始看看我能走多远的方法:

  1. 在我的 web.config 中创建两个 MembershipProvider,一个用于加密密码,另一个用于散列。
  2. 使用加密密码提供程序循环遍历所有用户。 (SqlMembershipProvider.GetAllUsers)
  3. 使用加密密码获取用户的密码提供者。 (MembershipUser.GetPassword)
  4. 使用哈希密码提供程序将用户的密码更改为相同的密码。 (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());
}

This is the approach I'd start with to see how far I got:

  1. Create two MembershipProviders in my web.config, one for encrypted passwords and one for hashed.
  2. Loop through all users using encrypted password provider. (SqlMembershipProvider.GetAllUsers)
  3. Get the user's password using encrypted password provider. (MembershipUser.GetPassword)
  4. Change the user's password to the same password using hashed password provider. (MembershipUser.ChangePassword)

So it'd be something like this:

    <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>

code:

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());
}
忆沫 2024-10-23 13:14:53

出于安全原因,在数据库中从加密密码切换到哈希值绝对是正确的决定。

通常是根据现有的哈希值创建哈希值加密的密码,您应该首先解密它们,然后散列它们。请注意,您将丢失(当您最终切换时)原始密码。相反,您将拥有用户密码的唯一指纹(哈希)。

还可以考虑使用盐进行散列(防御 rainbow table 等)并看看在慢速哈希算法中,例如 BCrypt (Codeplex & 文章:如何出于安全原因,安全存储密码)而不是像 MD5 这样的快速密码。

还请记住,将来切换哈希算法比将其从加密更改为哈希要花费更多的精力。所以你想第一次就做对;)

For security reasons, it's definitely the right decision to switch from encrypted passwords to hashes in your database.

Generally to create hashes out of your existing encrypted passwords, you should first decrypt them and then hash them. Be aware that you will loose (when you finally switch) the original passwords. Instead you're going to have a unique fingerprint (hash) of the users passwords.

Think also about using salt for the hashing (defense against rainbow tables etc.) and also have a look in slow hashing algorithms like BCrypt (Codeplex & Article: How To Safely Store A Password) for security reasons instead of fast ones like MD5.

Keep also in mind, that it will be way more effort to switch the hashing algorithm in the future than changing it from ecryption to hash. So you want to do it right the first time ;)

柠檬色的秋千 2024-10-23 13:14:53

我会提醒您不要随意对密码进行哈希处理,因为这种方法有很多注意事项。这篇关于散列密码的博客文章对我来说非常有见地,我认为你应该阅读它。为什么需要散列密码而不是加密密码?

I would caution you against hashing your passwords haphazardly since there are a lot of caveats to that approach. This Blog post about hashing passwords was very insightful to me, and I think that you should read it. Why do you want hashed passwords instead of encrypted?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文