0

我有一个用 SHA256 散列的密码。然后我有一个看起来像这样的盐:

啊啊啊啊啊啊啊啊啊==

在该过程结束时,它们都是字节数组,然后我将它们合并到一个新的字节数组中。

我的问题是,在将密码与盐合并时,我的哈希密码在最后缩短了一个字符。

预期输出:

uIxnpgdBQpSPJrqwYucIOeyOyqyCv7HbBfd74ovoxjI=AAAAAAAAAAAAAAAAAAAAAAAAA==

输出:

uIxnpgdBQpSPJrqwYucIOeyOyqyCv7HbBfd74ovoxjIAAAAAAAAAAAAAAAAAAAAAAAAA==

如您所见,在l之后缺少=

我的方法:

public static byte[] HashPassword(byte[] passwordToHash)
{
    byte[] hInput;
    byte[] hSalt = GetSalt();
    using(SHA256 sh = SHA256.Create())
    {
        hInput = sh.ComputeHash(passwordToHash);
    }
    byte[] SaltedPw = new byte[(hInput.Length+ 1 ) + (hSalt.Length + 3)];
    Array.Copy(hInput,0, SaltedPw, 0,hInput.Length);
    Array.Copy(hSalt, 0, SaltedPw, hInput.Length, hSalt.Length);
    return SaltedPw;
}

public static byte[] GetSalt()
{
    byte[] salt = new byte[16];
    return salt;
}

如何防止密码缩短?

4

1 回答 1

4

你这样做是不对的。您不得将盐添加到散列密码中。您必须将盐添加到纯密码中,然后进行哈希处理。关键是使当前或短密码的哈希无法识别。

base 64 编码仅应用于最终结果,以允许将密码哈希存储为字符串。因此,您将永远不必合并 base 64 字符串。=Base 64 字符串在末尾填充以获得长度为 4 的倍数。因此,您将永远不会=在中间看到 a。

public static string GetHashedPassword(string plainPassword, byte[] salt)
{
    byte[] passwordBytes = GetBytes(plainPassword);

    // Merge the password bytes and the salt bytes
    var mergedBytes = new byte[passwordBytes.Length + salt.Length];
    Array.Copy(passwordBytes, mergedBytes, passwordBytes.Length);
    Array.Copy(salt, 0, mergedBytes, passwordBytes.Length, salt.Length);

    // Now hash password + salt
    byte[] hash;
    using (var sha = SHA256.Create()) {
        hash = sha.ComputeHash(mergedBytes);
    }
    return Base64Encode(hash);
}

你还需要这个:

public static string Base64Encode(byte[] bytes)
{
    return System.Convert.ToBase64String(bytes);
}

static byte[] GetBytes(string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

为每个密码创建随机盐字节,并将盐作为单独的信息与散列密码一起存储。像这样,每个密码都有不同的盐。这使得预计算字典攻击/彩虹表攻击不可行。salt不需要加密。您可能还希望将其存储为 base 64 字符串。要再次获取盐字节,您将需要Convert.FromBase64String().

于 2019-03-09T19:04:24.190 回答