I am writing a class to hash passwords which implements Key Stretching by using the System.Security.Cryptography.Rfc2898DeriveBytes class to generate the keys used to compute the hash value.
The code essentially does this:
// Higher iterations value results in better key strength
var db = new Rfc2898DeriveBytes(password + salt + secretKeyFromConfigFile,
saltAsBytes,
iterations);
byte[] hashKey = db.GetBytes(64); // 64 bytes is the recommended size for the HMACSHA512 class
var sha512 = new System.Security.Cryptography.HMACSHA512(hashKey);
byte[] hashInput = System.Text.Encoding.UTF8.GetBytes(password + salt + secretKeyFromConfigFile);
byte[] hash = sha512.ComputeHash(hashInput);
return System.Convert.ToBase64String(hash);
The documentation for System.Security.Cryptography.Rfc2898DeriveBytes indicates that it uses "... a pseudo-random number generator based on System.Security.Cryptography.HMACSHA1" to derive the key.
Since SHA512 is better than SHA1 Would it be better to simply apply the SHA512 hash function like so?
byte[] hash;
for (int i = 0; i < iterations; i++)
{
hash = sha512.ComputeHash(hash ?? hashInput);
}
return System.Convert.ToBase64String(hash);
What is the difference between strengthening the key (as shown in the 1st code block) and strengthening the hash (as shown in the 2nd code block)?
What is the preferred method to do key stretching when hashing passwords?