简体   繁体   中英

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.

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. The code below returns true. All I changed was salt: Encoding.ASCII.GetBytes(dbPasswordSalt), to 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;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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