使用密码填充密码对"彩虹表"进行逆向工程的密码哈希保护

ahm*_*md0 0 c# asp.net passwords cryptography rainbowtable

我已经看到这篇文章描述了在数据库中存储"无盐"密码哈希的危险,这些密码哈希可能会使用所谓的" 彩虹表 " 进行逆向工程.

它还带有这个C#代码示例,它基本上需要在用户密码数据库表中存储两个哈希列(而不是传统的 - 一个.)这种方法的问题是我已经建立了一个带有未加密的用户密码的数据库表哈希,并添加新列将需要重组数据库.所以在我这样做之前,我一直在寻找另一种选择,这就是我想出的.

这里的函数不是简单地计算密码上的SHA1哈希值,而是用一长串伪随机(但一致)数据填充它,然后计算哈希:

byte[] computeSecureHash(string strUserPassword)
{
    //RETURN: = SHA1 byte array on the 'strUserPassword'

    //Make simple junk array based on the password
    ushort v = 117;
    byte[] arrJunk = new byte[24];
    for (int c = 0, i = 0; i < arrJunk.Length; i++)
    {
        v ^= strUserPassword[c++];
        v *= 7;
        arrJunk[i] = (byte)v;

        if (c >= strUserPassword.Length)
            c = 0;
    }

    //Make crypto byte array based on the password
    Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(strUserPassword, arrJunk);
    pbkdf2.IterationCount = 1000;
    byte[] arrCrypto = pbkdf2.GetBytes(128);

    //Pad actual password
    string strUserPassword_Padded = "";

    const string strChars2Use = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`-=[]\\;',./~!@#$%^&*()_+{}|:\"<>?";
    int nHalfArrCrypto = arrCrypto.Length / 2;

    //Left side
    for (int i = 0; i < nHalfArrCrypto; i++)
    {
        strUserPassword_Padded += strChars2Use[arrCrypto[i] % strChars2Use.Length];
    }

    strUserPassword_Padded += strUserPassword;

    //Right side
    for (int i = nHalfArrCrypto; i < arrCrypto.Length; i++)
    {
        strUserPassword_Padded += strChars2Use[arrCrypto[i] % strChars2Use.Length];
    }

    //For user's password "123"
    //the 'strUserPassword_Padded' becomes:
    //"bwDR]_B>H5t-k:eIq?r_wGBWqWfs#tcAE~DQ5?(Pbj#<+Cw:9(r!B[f_.S<pCjn-123b9l3<Sz^D~>G}v)?NuHT4BZ-pI2$W[kW1e4KO\"`rTg3H`}&jmtrFh1J5c72:})tQ"

    //And now compuse SHA1 on the padded password
    SHA1 sha1 = new SHA1CryptoServiceProvider();
    byte[] bytesInputData = System.Text.Encoding.UTF8.GetBytes(strUserPassword_Padded);
    return sha1.ComputeHash(bytesInputData);
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,有人可以审查这段代码并告诉我这样做的危险与作者在他的代码中建议的方式有什么危险?在我的代码示例的情况下,我将只需要在数据库中存储一个哈希而不是两个(密码哈希+盐哈希).

Oli*_*rth 6

从密码中获得的盐几乎没有意义; 你刚刚创建了一个稍微不同(但是常量)的哈希函数.可以使用单个彩虹表(尽管是自定义表)来定位整个数据库.

此外,如果从密码派生盐,则相同的密码显示为相同的"密码哈希".简单的密码可能会显示为重复 - 实际上您正在生成自己的彩虹表.

为每个密码存储唯一的,独立生成的盐的重点是每个密码都使用唯一的哈希函数进行哈希处理.因此,没有一个彩虹表可以在整个数据库中使用.

  • @ ahmd0:你称它为什么并不重要.效果是一样的;) (3认同)