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)