using System.Security.Cryptography;
public static void Main()
Console.WriteLine("PasswordString 原始密碼字串");
Console.WriteLine("Hello World");
Console.WriteLine("=======================================");
Console.WriteLine("PasswordHash, same password have different hash and salt 密碼雜湊值,相同的密碼也會有不同的雜湊和鹽");
Console.WriteLine(PasswordHash.GetPasswordHash("Hello World"));
Console.WriteLine(PasswordHash.GetPasswordHash("Hello World"));
Console.WriteLine(PasswordHash.GetPasswordHash("Hello World"));
Console.WriteLine("=======================================");
Console.WriteLine("VerifyPasswordHash 驗證密碼雜湊是否與輸入的密碼相同");
Console.WriteLine(PasswordHash.VerifyPasswordHash("Hello World","4096:hQnjEQoZH9Q2h6bCkPirW4dKbU1erHnyicjca98OkA4=:++Yslxkt1IBY0e87OgmzBbBSgRuRlcpwPb5fMkvWgtQ="));
Console.WriteLine("=======================================");
Console.WriteLine("Memory is high 可以觀察到右邊消耗記憶體不少");
private const int SaltByteSize = 32;
private const int HashByteSize = 32;
private const int Iterations = 4096;
private static string GetSalt()
var cryptoProvider = new RNGCryptoServiceProvider();
byte[] b_salt = new byte[SaltByteSize];
cryptoProvider.GetBytes(b_salt);
return Convert.ToBase64String(b_salt);
public static string GetPasswordHash(string password)
byte[] saltBytes = Convert.FromBase64String(salt);
using (var pbkdf2 = new Rfc2898DeriveBytes(
HashAlgorithmName.SHA512))
derived = pbkdf2.GetBytes(HashByteSize);
return string.Format("{0}:{1}:{2}", Iterations, Convert.ToBase64String(derived), Convert.ToBase64String(saltBytes));
public static bool VerifyPasswordHash(string password, string hash)
string[] parts = hash.Split(new char[] { ':' });
byte[] saltBytes = Convert.FromBase64String(parts[2]);
int iterations = Convert.ToInt32(parts[0]);
using (var pbkdf2 = new Rfc2898DeriveBytes(
HashAlgorithmName.SHA512))
derived = pbkdf2.GetBytes(HashByteSize);
string new_hash = string.Format("{0}:{1}:{2}", Iterations, Convert.ToBase64String(derived), Convert.ToBase64String(saltBytes));