How to hash password

We know that it’s very dangerous to hold explicit passwords in a database. That is why it’s the best to get them hash but how to do it?

Hash password

In the first step we need to create salt.

Salt( Via Wikipedia ) – is random data that is used as an additional input to a one-way function that “hashes” a password or passphrase. The primary function of salts is to defend against dictionary attacks or against its hashed equivalent, a pre-computed rainbow table attack. link

The function responsible for generating salt is as follows:

public string GetSalt()
{
    var saltInBytes = new byte[40];
    var rng = RandomNumberGenerator.Create();
    rng.GetBytes(saltInBytes);
    return Convert.ToBase64String(saltInBytes);
}

private static byte[] GetBytes(string value)
{
    var bytes = new byte[value.Length * sizeof(char)];
    Buffer.BlockCopy(value.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

And then we can use a ready-made hashing alorithm of the class Rfc2898DeriveBytes in C#.

public string GetHash(string password, string salt)
{
    var hash = new Rfc2898DeriveBytes(password, GetBytes(salt), 1000);
    return Convert.ToBase64String(hash.GetBytes(40));
}

Let’s see that our system will correct hashing our password.

[Fact]
public void Hash_system_should_return_the_correct_hashed_password()
{
    const string password = "secretpw";
    var hashSystem = new HashPw();

    var salt = "CV5QNYON27MkyFrbiZViitcxfdXZHdHvsE7kSAu4UQ5f9GkxmhMszA ==";
    var hashPassword = hashSystem.GetHash(password, salt);

    Assert.Equal("AGd+jMv/HauI86d9nRSa568irLdYgWjrHfVALjQ1g04VJLSUucMnEA==", hashPassword);
}

In this approeach with the same salt and password our system will generates the same hash password. If we give him diffrent salt, then diffrent hash password will be generated.

So in our case two users with the same password will have diffrent hash password.

[Fact]
public void Hash_system_all_time_genereate_the_same_hash_password_if_we_give_him_the_same_salt()
{
    const string password = "secretpw";
    var hashSystem = new HashPw();

    var salt = hashSystem.GetSalt();
    var hashPassword = hashSystem.GetHash(password, salt);
    var secondHashPassword = hashSystem.GetHash(password, salt);

    Assert.Equal(hashPassword, secondHashPassword);
}

[Fact]
public void Hash_password_will_be_diffrent_for_the_same_user_password_with_diffrent_salt()
{
    const string password = "secretpw";
    var hashSystem = new HashPw();

    var salt = hashSystem.GetSalt();
    var hashPassword = hashSystem.GetHash(password, salt);
    var saltForSecondUser = hashSystem.GetSalt();
    var secondHashPassword = hashSystem.GetHash(password, saltForSecondUser);

    Assert.NotEqual(hashPassword, secondHashPassword);
}

And here is the confirmation. 😉

  hashtest

Link to the project.

Additional.

Difference between pseudo number and security number.
secure and pseudo number

4 Comments on “How to hash password”

  1. I do not like randomness in unit tests.

    What is returned from RandomNumberGenerator.Create();? it’s like ‘return new Random(42);’ ?

    If seed is not constant then you cannot be sure if salt generated in Hash_password_will_be_diffrent_for_the_same_user_password_with_diffrent_salt() will be always diffrent from each other.

    1. 1. Difference it’s that random generate for us “pseudo random” but randomnumbergenerator generate for us “more secure” random.
      Random vs EncryptRandom
      2. Yes but for me it does not matter that salt will be the same for different passwords. Because class Rfc2898DeriveBytes generate for us diffrent “hash” at the end.

  2. The probability is very, but very small. Adding to that, we generate a “secure random” instead of “pseudo random”.

  3. Jeżeli chodzi o wyjście poza zakres to o bym się nie martwił.
    Dla mnie sprawdza się kopiowanie tablic “ręcznie”. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *