3

我正在接管以前开发人员编写的系统。系统有管理员批准用户帐户,当他们这样做时,系统使用以下方法对密码进行哈希处理并将其保存到数据库中。它将未散列的密码发送给用户。当用户登录系统时,系统使用完全相同的方法对用户输入的内容进行哈希处理,并将其与数据库值进行比较。我们已经遇到过几次数据库条目与用户的条目不匹配的情况。因此,该方法似乎并不总是对相同的值进行哈希处理。有谁知道这种散列方法是否不可靠以及如何使其可靠?谢谢。

    private string HashPassword(string password)
    {
        string hashedPassword = string.Empty;

        // Convert plain text into a byte array.
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(password);

        // Allocate array, which will hold plain text and salt.
        byte[] plainTextWithSaltBytes =
                new byte[plainTextBytes.Length + SALT.Length];

        // Copy plain text bytes into resulting array.
        for(int i = 0; i < plainTextBytes.Length; i++)
            plainTextWithSaltBytes[i] = plainTextBytes[i];

        // Append salt bytes to the resulting array.
        for(int i = 0; i < SALT.Length; i++)
            plainTextWithSaltBytes[plainTextBytes.Length + i] = SALT[i];

        // Because we support multiple hashing algorithms, we must define
        // hash object as a common (abstract) base class. We will specify the
        // actual hashing algorithm class later during object creation.
        HashAlgorithm hash = new SHA256Managed();

        // Compute hash value of our plain text with appended salt.
        byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes);

        // Create array which will hold hash and original salt bytes.
        byte[] hashWithSaltBytes = new byte[hashBytes.Length +
                                            SALT.Length];
        // Copy hash bytes into resulting array.
        for(int i = 0; i < hashBytes.Length; i++)
            hashWithSaltBytes[i] = hashBytes[i];

        // Append salt bytes to the result.
        for(int i = 0; i < SALT.Length; i++)
            hashWithSaltBytes[hashBytes.Length + i] = SALT[i];

        // Convert result into a base64-encoded string.
        hashedPassword = Convert.ToBase64String(hashWithSaltBytes);

        return hashedPassword;
    }
4

2 回答 2

4

此函数使用 salt进行散列。这是一种确保它为相同密码产生不同哈希并使表查找更加困难的技术。

仅当您具有相同的盐值时,哈希才相同。

有关此技术的详细信息,请参阅维基百科http://en.wikipedia.org/wiki/Salt_%28cryptography%29

引用http://msdn.microsoft.com/en-us/magazine/cc164107.aspx

要减慢攻击速度,请使用盐。Salt是一种在散列密码之前对密码进行调味的方法,使攻击者的预计算字典变得无用。这是它是如何完成的。每当您向数据库添加条目时,您都会计算一个随机的数字字符串以用作盐。当您想要计算 Alice 密码的哈希值时,您可以查找 Alice 帐户的 salt 值,将其添加到密码中,然后将它们一起进行哈希处理。生成的数据库如下所示:

<users>
  <user name='Alice' salt='Tu72*&' password='6DB80AE7...'/>
  <user name='Bob'   salt='N5sb#X' password='096B1085...'/>
  <user name='Fred'  salt='q-V3bi' password='9118812E...'/>
</users>

请注意,现在无法判断 Bob 和 Fred 使用的是相同的密码。请注意,盐本身并不是秘密。

于 2010-05-17T04:52:29.237 回答
1

如果该过程不使用任何随机决策(即,它是完全确定性的),并且使用的算法的实现是相同的(它们应该是 - SHA256 应该在任何地方都表现得完全相同,并且同样如此对于 Base64 字符串),那么算法本身“不散列相同的值”的可能性很小。

如果你不能重现错误(意思是:找到一些值,在服务器上散列时总是产生一个散列,而在客户端散列时总是产生另一个散列),你应该确保这些值被正确地传输和接收。也许客户得到了未经哈希处理的密码?也许服务器正在从客户端接收损坏的数据?也许服务器数据库本身的数据发生了某种变化?确保每笔交易都经过验证,即用户无法收到损坏的密码。

于 2010-03-19T15:09:00.013 回答