Blake Rivell
Blake Rivell

Reputation: 13895

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?

Upvotes: 2

Views: 2637

Answers (2)

  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.

Upvotes: 1

Joshua Trimm
Joshua Trimm

Reputation: 63

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;
    }

Upvotes: 1

Related Questions