I'm implementing a password hashing method for a website. The code below is part of the User class.
Any pointers on what I could do better?
private string GenerateSalt(int SaltLength) {
using (var rng = new RNGCryptoServiceProvider()) {
var salt_bytes = new byte[SaltLength];
rng.GetNonZeroBytes(salt_bytes);
return Convert.ToBase64String(salt_bytes);
}
}
private string GeneratePasswordHash(string Password) {
//create an hmac hash of the password using the pepper value as the key
using (var hmacsha = new HMACSHA512(ConvertStringToBytes(ConfigurationManager.AppSettings["PasswordHashPepper"]))) {
byte[] initial_hash = hmacsha.ComputeHash(ConvertStringToBytes(Password));
//generate a key value using pbkdf2 that will serve as the password hash
using (var pbkdf2 = new Rfc2898DeriveBytes(initial_hash, ConvertStringToBytes(this.Salt), int.Parse(ConfigurationManager.AppSettings["PasswordHashWorkFactor"]))) {
return ConvertBytesToString(pbkdf2.GetBytes(128));
}
}
}
private byte[] ConvertStringToBytes(string conversionString) {
byte[] bytes = new byte[conversionString.Length * sizeof(char)];
System.Buffer.BlockCopy(conversionString.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
private string ConvertBytesToString(byte[] conversionBytes) {
char[] chars = new char[conversionBytes.Length / sizeof(char)];
System.Buffer.BlockCopy(conversionBytes, 0, chars, 0, conversionBytes.Length);
return new string(chars);
}
public void SetNewPassword(string NewPassword) {
this.Salt = GenerateSalt(64);
this.PasswordHash = GeneratePasswordHash(NewPassword);
}
public bool ValidatePassword(string AttemptedPassword) {
return (GeneratePasswordHash(AttemptedPassword) == this.PasswordHash);
}