Rfc2898DeriveBytes密码匹配string而不是byte[]

本文关键字:byte 密码 string Rfc2898DeriveBytes | 更新日期: 2023-09-27 18:07:37

我正在尝试创建一个具有登录和密码凭证的身份验证服务器,我使用了本教程,给了我以下PasswordHash类。当我使用Verify方法与字符串,但我不想通过UDP发送未加密的密码出于安全原因,但当我测试哈希直接通过提供它的字节数组,它返回false(如下面的类所示)。

public sealed class PasswordHash
{
    const int SaltSize = 16, HashSize = 20, HashIter = 10000;
    readonly byte[] _salt, _hash;
    private PasswordHash() { }
    public PasswordHash(string password)
    {
        new RNGCryptoServiceProvider().GetBytes(_salt = new byte[SaltSize]);
        _hash = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize);
    }
    public PasswordHash(byte[] hashBytes)
    {
        Array.Copy(hashBytes, 0, _salt = new byte[SaltSize], 0, SaltSize);
        Array.Copy(hashBytes, SaltSize, _hash = new byte[HashSize], 0, HashSize);
    }
    public PasswordHash(byte[] salt, byte[] hash)
    {
        Array.Copy(salt, 0, _salt = new byte[SaltSize], 0, SaltSize);
        Array.Copy(hash, 0, _hash = new byte[HashSize], 0, HashSize);
    }
    public byte[] ToArray()
    {
        byte[] hashBytes = new byte[SaltSize + HashSize];
        Array.Copy(_salt, 0, hashBytes, 0, SaltSize);
        Array.Copy(_hash, 0, hashBytes, SaltSize, HashSize);
        return hashBytes;
    }
    public byte[] Salt { get { return (byte[])_salt.Clone(); } }
    public byte[] Hash { get { return (byte[])_hash.Clone(); } }
    public bool Verify(string password)
    {
        byte[] test = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize);
        for (int i = 0; i < HashSize; i++)
            if (test[i] != _hash[i])
                return false;
        return true;
    }
    public bool Verify(byte[] passwordHash) 
    {
        for (int i = 0; i < HashSize; i++)
            if (passwordHash[i] != _hash[i])
                return false;
        return true;
    }
}

我用

测试它
bool test = new PasswordHash("test123").Verify("test123"); //TRUE
bool test2 = new PasswordHash("test123").Verify(newPasswordHash("test123").ToArray()); //FALSE

因此,正如Nissim指出的那样,它们不匹配,因为每次我调用new PasswordHash().时都会随机生成盐。是否有绕过添加到字节[]中的盐的方法?

Rfc2898DeriveBytes密码匹配string而不是byte[]

每次调用PasswordHash的构造函数时,它都会创建一个新的salt,因此在以下示例中:

byte[] pass1 = new HashPassword("abc").ToArray();
byte[] pass2 = new HashPassword("abc").ToArray();

pass1与pass2不同