HashedPasswordEntity.cs
public class HashedPasswordEntity
{
[SuppressMessage("Microsoft.Design", "CA1051:不要声明可见实例字段", Justification = "It's readonly.")]
public readonly string Hash;
[SuppressMessage("Microsoft.Design", "CA1051:不要声明可见实例字段", Justification = "It's readonly.")]
public readonly string Salt;
public HashedPasswordEntity(string hash, string salt)
{
Hash = hash;
Salt = salt;
}
}
Hasher.cs
using System;
using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
using System.Text;
namespace HashLibrary
{
public class Hasher
{
private static Encoding Encoding = Encoding.GetEncoding(437);
public readonly int HashLength;
public readonly int SaltLength;
public Hasher() : this(32, 32) { }
public Hasher(int hashLength, int saltLength)
{
if (hashLength <= 0)
{
throw new ArgumentOutOfRangeException("hashLength");
}
if (saltLength <= 0)
{
throw new ArgumentOutOfRangeException("saltLength");
}
HashLength = hashLength;
SaltLength = saltLength;
}
public bool Check(string password, HashedPasswordEntity hashed)
{
if (password == null)
throw new ArgumentNullException("password");
if (hashed == null)
throw new ArgumentNullException("hashed");
var bytes = Encoding.GetBytes(hashed.Salt);
return hashed.Hash == HashPassword(password, bytes);
}
public HashedPasswordEntity HashPassword(string password)
{
var bytes = GenerateSalt();
var hash = HashPassword(password, bytes);
var salt = Encoding.GetString(bytes);
return new HashedPasswordEntity(hash, salt);
}
private string HashPassword(string password, byte[] salt)
{
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt))
{
var bytes = pbkdf2.GetBytes(HashLength);
return Encoding.GetString(bytes);
}
}
private byte[] GenerateSalt()
{
var random = new Random(unchecked((int)DateTime.Now.Ticks));
var salt = new byte[SaltLength];
random.NextBytes(salt);
return salt;
}
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
Empty()
Console.WriteLine("-----------------------------------------")
DefaultLengths()
Console.WriteLine("-----------------------------------------")
CustomLengths()
Console.ReadKey()
}
public static void Empty()
{
var hasher = new Hasher()
var hashed = hasher.HashPassword(string.Empty)
Console.WriteLine(hasher.Check(string.Empty, hashed))
Console.WriteLine(hasher.Check("", hashed))
Console.WriteLine(hasher.HashLength+"-----------"+hashed.Hash.Length)
Console.WriteLine(hasher.SaltLength + "-----------" + hashed.Salt.Length)
}
public static void DefaultLengths()
{
var hasher = new Hasher()
var hashed = hasher.HashPassword("foo")
Console.WriteLine(hasher.Check("foo", hashed))
Console.WriteLine(hasher.Check("bar", hashed))
Console.WriteLine(hasher.HashLength + "-----------" + hashed.Hash.Length)
Console.WriteLine(hasher.SaltLength + "-----------" + hashed.Salt.Length)
}
public static void CustomLengths()
{
var hasher = new Hasher(100, 8)
var hashed = hasher.HashPassword("foo")
Console.WriteLine(hasher.Check("foo", hashed))
Console.WriteLine(hasher.Check("bar", hashed))
Console.WriteLine(hasher.HashLength + "-----------" + hashed.Hash.Length)
Console.WriteLine(hasher.SaltLength + "-----------" + hashed.Salt.Length)
}
}
运行结果如图:
