简体   繁体   English

使用 Pbkdf2 加密使用 Salt 加密和验证散列密码

[英]Encrypting and Verifying a Hashed Password with Salt using Pbkdf2 Encryption

I am using the following code to created a hashed password and salt:我正在使用以下代码创建散列密码和盐:

// generate a 128-bit salt using a secure PRNG
byte[] salt = new byte[128 / 8];
using (var rng = RandomNumberGenerator.Create())
{
    rng.GetBytes(salt);
}

// derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations)
string hashedPassword = Convert.ToBase64String(KeyDerivation.Pbkdf2(
    password: password,
    salt: salt,
    prf: KeyDerivationPrf.HMACSHA1,
    iterationCount: 10000,
    numBytesRequested: 256 / 8));

I am storing the HashedPassword and Salt in the database.我将 HashedPassword 和 Salt 存储在数据库中。

Now I want to verify the password on User Login:现在我想在用户登录时验证密码:

public bool VerifyPassword(string userEnteredPassword, string dbPasswordHash, string dbPasswordSalt)
{
    string hashedPassword = Convert.ToBase64String(KeyDerivation.Pbkdf2(
        password: userEnteredPassword,
        salt: Encoding.ASCII.GetBytes(dbPasswordSalt),
        prf: KeyDerivationPrf.HMACSHA1,
        iterationCount: 10000,
        numBytesRequested: 256 / 8));

    return dbPasswordHash == hashedPassword;
}

This is not working, I am getting a completely different hashed password than the one stored in the database.这不起作用,我得到的散列密码与存储在数据库中的密码完全不同。 From what I understand you are supposed to prepend the salt to the password that the user enters when logging in and then run the same Hash Password function.据我了解,您应该在用户登录时输入的密码前添加盐,然后运行相同的哈希密码功能。 Wouldn't the above be the equivalent to that?上面的不是等价的吗?

  1. Create the password创建密码

Create a salt with the bellow code:使用以下代码创建盐:

    byte[] salt = new byte[128 / 8];
    using (var rng = RandomNumberGenerator.Create())
    {
        rng.GetBytes(salt);
    }
    return Convert.ToBase64String(salt);

Then create a hashed password using that salt.然后使用该盐创建一个散列密码。

string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
        password: password,
        salt: salt,
        prf: KeyDerivationPrf.HMACSHA1,
        iterationCount: 10000,
        numBytesRequested: 256 / 8));

Save the salt that used in somewhere (ex: database) Save the hashed password for that user.保存在某处使用的盐(例如:数据库)保存该用户的散列密码。

  1. Validate the password验证密码
    • Retrieve the salt and hashed password for that user.检索该用户的盐和散列密码。
    • Create a hashed password using the retrieved salt and the user entered password.使用检索到的盐和用户输入的密码创建散列密码。
    • Check newly hashed password and stored password is the same.检查新散列的密码和存储的密码是否相同。

As Maarten Bodewes mentioned, ASCII was the problem.正如 Maarten Bodewes 提到的,ASCII 是问题所在。 The code below returns true.下面的代码返回true。 All I changed was salt: Encoding.ASCII.GetBytes(dbPasswordSalt), to salt: System.Convert.FromBase64String(dbPasswordSalt),我改变的只是salt: Encoding.ASCII.GetBytes(dbPasswordSalt), salt: System.Convert.FromBase64String(dbPasswordSalt),

public bool VerifyPassword(string userEnteredPassword, string dbPasswordHash, string dbPasswordSalt)
    {
        Console.WriteLine(dbPasswordSalt.ToString());
        Console.WriteLine(dbPasswordHash.ToString());

        string hashedPassword = Convert.ToBase64String(KeyDerivation.Pbkdf2(
            password: userEnteredPassword,
            salt: System.Convert.FromBase64String(dbPasswordSalt),///Encoding.ASCII.GetBytes(dbPasswordSalt),
            prf: KeyDerivationPrf.HMACSHA1,
            iterationCount: 10000,
            numBytesRequested: 256 / 8));
        Console.WriteLine(hashedPassword.ToString());
        return dbPasswordHash == hashedPassword;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM