Skip to content

Instantly share code, notes, and snippets.

@khellang
Last active August 29, 2015 13:56
Show Gist options
  • Save khellang/8985124 to your computer and use it in GitHub Desktop.
Save khellang/8985124 to your computer and use it in GitHub Desktop.
public class ExampleUsage
{
private readonly IPasswordHasher _hasher;
public ExampleUsage(IPasswordHasher hasher)
{
_hasher = hasher;
}
public void Register(string username, string password)
{
var hashBase64 = default(string);
var saltBase64 = default(string);
_hasher.Generate(password, out hashBase64, out saltBase64);
Database.Save(new User
{
Username = username,
PasswordHash = hashBase64,
Salt = saltBase64
});
}
public bool Login(string username, string password)
{
var user = Database.Get(username);
if (user == null)
{
return false;
}
return _hasher.Verify(password, user.PasswordHash, user.Salt);
}
}
public interface IPasswordHasher
{
void Generate(string password, out string hashBase64, out string saltBase64);
bool Verify(string password, string hashBase64, string saltBase64);
}
public class PasswordHasher : IPasswordHasher
{
private readonly int _saltSize;
private readonly int _hashSize;
private readonly int _iterations;
public PasswordHasher(int saltSize = 10, int hashSize = 40, int iterations = 10000)
{
_saltSize = saltSize;
_hashSize = hashSize;
_iterations = iterations;
}
public void Generate(string password, out string hashBase64, out string saltBase64)
{
using (var hashGenerator = new Rfc2898DeriveBytes(password, _saltSize, _iterations))
{
hashBase64 = Convert.ToBase64String(hashGenerator.GetBytes(_hashSize));
saltBase64 = Convert.ToBase64String(hashGenerator.Salt);
}
}
public bool Verify(string password, string hashBase64, string saltBase64)
{
var hashBytes = Convert.FromBase64String(hashBase64);
var saltBytes = Convert.FromBase64String(saltBase64);
using (var hashGenerator = new Rfc2898DeriveBytes(password, saltBytes, _iterations))
{
return SlowEquals(hashGenerator.GetBytes(hashBytes.Length), hashBytes);
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private static bool SlowEquals(IList<byte> a, IList<byte> b)
{
var diff = a.Count ^ b.Count;
for (var i = 0; i < a.Count && i < b.Count; i++)
{
diff |= a[i] ^ b[i];
}
return diff == 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment