【问题标题】:Rfc2898DeriveBytes password matches with string and not with byte[]Rfc2898DeriveBytes 密码匹配字符串而不是字节[]
【发布时间】:2015-11-06 08:06:09
【问题描述】:

我正在尝试使用登录名和密码凭据创建身份验证服务器,我使用了this tutorial,它为我提供了以下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(). 时都会随机生成盐,有没有绕过添加到字节 [] 中的盐?

【问题讨论】:

    标签: c# authentication hash passwords


    【解决方案1】:

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

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

    pass1 与 pass2 不同

    【讨论】:

    • 哦!那么有没有办法绕过盐来验证两个哈希?
    • 您可以向HashPassword 类添加一个构造函数,该类将获取盐作为参数:public PasswordHash(string password, byte[] salt) { _salt = (byte[])salt.Clone(); _hash = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize); }
    • 非常感谢。稍后会测试它。
    猜你喜欢
    • 1970-01-01
    • 2012-04-01
    • 2019-02-11
    • 2017-11-22
    • 2015-08-17
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    相关资源
    最近更新 更多