Standing on the shoulders of giants.
 Tuesday, June 10, 2008

When hashing a password, you usually use a salt to to make it harder for an attacker to attack the password (see [0]), since the salt is needed to calculate the hash, the same salt is needed to verify a password.

The submitted Hash( Salt + Password ) must be equal to the stored Hash( Salt + Password ).

The common place to store the salt is in a separate field alongside the hash, but this may cause either one to get out-of-sync with the other. A better solution is to concatenate the salt and the hash and store both in one byte array.

static void Main(string[] args)
{
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

    byte[] salt = new byte[0x10];
    rng.GetBytes(salt);

    Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes("the password", salt, /*iterations*/ 5);

    byte[] passHash = deriveBytes.GetBytes(0x100);

    byte[] result = Merge(passHash, salt);
}

private static byte[] Merge(byte[] first, byte[] second)
{
    byte[] result = new byte[first.Length + second.Length];
    Buffer.BlockCopy(first, 0, result, 0, first.Length);

    Buffer.BlockCopy(second, 0, result, first.Length, second.Length);

    return result;
}

Extracting the salt from the hash is relatively simple:

private static byte[] ExtractSalt(byte[] hash, int length)
{
    byte[] salt = new byte[length];

    Buffer.BlockCopy(hash, hash.Length - length, salt, 0, length);

    return salt;
}

You use this salt to generate the hash for the password you want to check and after adding the salt to the end both byte arrays must be equal.

[0] See p.350-352 in Practical Cryptography by Niels Ferguson and Bruce Schneier why salting a password is a good idea.

Sample: HashSample.cs.txt (1.78 KB)

10 Jun 2008 13:39 W. Europe Daylight Time  #    Comments [4] - Trackback
Codesnippet | Security

Saturday, June 14, 2008 7:55:02 PM (W. Europe Standard Time, UTC+01:00)
Hi Paul

I like the idea of attaching the salt to the hash.

Are you using the Rfc2898DeriveBytes to compute a hash because it combines the password and salt more easily than say one of the hash algorithm providers like SHA1CryptoServiceProvider? I've not seen this done before.

Tony
Saturday, June 14, 2008 8:00:11 PM (W. Europe Standard Time, UTC+01:00)
I'm using the Rfc2898DeriveBytes because it does the iterations for you, which is one less thing to remember.
Sunday, June 15, 2008 6:08:13 AM (W. Europe Standard Time, UTC+01:00)
Ok - understood. The key being used as the hash is very large - 2048 bits (vs 160 bits or above using SHA1/2)- so is there a tradoff in performance to produce a very strong hash like this?
Sunday, June 15, 2008 1:26:59 PM (W. Europe Standard Time, UTC+01:00)
The creation of the hash will be a bit slower, but this is mainly a problem when you have to try a lot of keys to gain access (in a dictionary attack for example).
Comments are closed.
Subscribe
About
newtelligence dasBlog 2.1.7309.765
Admin
All Content © Copyright 2008, Paul van Brenk
DasBlog theme 'Business' created by Christoph De Baene (delarou)