/// <summary> /// Hashes the passed in string with a random salt using the Pbkdf2 hashing algorithm using HMAC SHA512. The salt is embedded /// into the result which is then Base64 encoded as a string. /// </summary> /// <param name="password">The string to hash. If this string is already an MD5, basd64 encoded hash, set performPreMD5Hashing to false</param> /// <param name="performPreMD5Hashing">Old versions of HnD used MD5 hashed passwords and to migrate these to Pbkdf2 we rehashed the MD5Hashed variants. /// To signal the passed in password is already an MD5 base64 hash, this flag has to be false. If the password is the plain password as specified /// by the user, this flag has to be true. </param> /// <returns>the base64 encoded byte array which contains the salt and the hash and which is ready to be saved in the database</returns> public static string HashPassword(string password, bool performPreMD5Hashing) { var salt = new byte[PasswordSaltLengthBytes]; _rng.GetBytes(salt); var resultAsByteArray = HnDGeneralUtils.PerformPbkdf2Hashing(password, salt, performPreMD5Hashing); return(Convert.ToBase64String(resultAsByteArray)); }
/// <summary> /// /// </summary> /// <param name="password">The string to hash. If this string is already an MD5, basd64 encoded hash, set performPreMD5Hashing to false</param> /// <param name="salt">the byte array with the rng produced salt to use for hashing the password specified</param> /// <param name="performPreMD5Hashing">Old versions of HnD used MD5 hashed passwords and to migrate these to Pbkdf2 we rehashed the MD5Hashed variants. /// To signal the passed in password is already an MD5 base64 hash, this flag has to be false. If the password is the plain password as specified /// by the user, this flag has to be true. </param> /// <returns>byte array with the salt in the lower indexes and the pbkdf2 hash bytes in the higher indexes</returns> private static byte[] PerformPbkdf2Hashing(string password, byte[] salt, bool performPreMD5Hashing) { // see if we need to pre-hash the passed in string. See note above. var passwordToHash = performPreMD5Hashing ? HnDGeneralUtils.CreateMD5HashedBase64String(password) : password; var prf = KeyDerivationPrf.HMACSHA512; byte[] hashedPassword = KeyDerivation.Pbkdf2(passwordToHash, salt, prf, Pbkdf2Iterations, Pbkdf2HashLengthBytes); // create a byte array with both the salt (in the lower indices) and the hashed result (higher indices) and base64 encode that as a single string. // [<salt> (PasswordSaltLengthBytes in length) | <Pbkdf2 hashed pwd bytes> (Pbkdf2HashLengthBytes in length] var resultAsByteArray = new byte[PasswordSaltLengthBytes + Pbkdf2HashLengthBytes]; Array.Copy(salt, 0, resultAsByteArray, 0, PasswordSaltLengthBytes); Array.Copy(hashedPassword, 0, resultAsByteArray, PasswordSaltLengthBytes, Pbkdf2HashLengthBytes); return(resultAsByteArray); }