feat: implement password hasher

This commit is contained in:
Stevan Freeborn
2026-02-03 04:38:40 -06:00
parent 00d7c977e7
commit 647b185d40
2 changed files with 108 additions and 0 deletions
@@ -0,0 +1,66 @@
using System.Security.Cryptography;
namespace FiscalOS.API.Identity;
internal interface IPasswordHasher
{
string Hash(string password);
bool Verify(string providedPassword, string hashedPassword);
}
internal class PasswordHasher : IPasswordHasher
{
private const int SaltSize = 16;
private const int HashSize = 32;
private const int Iterations = 100_000;
private static readonly HashAlgorithmName HashAlgorithm = HashAlgorithmName.SHA512;
private PasswordHasher()
{
}
public static PasswordHasher New()
{
return new();
}
public string Hash(string password)
{
var salt = RandomNumberGenerator.GetBytes(SaltSize);
var hash = Rfc2898DeriveBytes.Pbkdf2(
password,
salt,
Iterations,
HashAlgorithm,
HashSize
);
var hashBytes = new byte[SaltSize + HashSize];
Array.Copy(salt, 0, hashBytes, 0, SaltSize);
Array.Copy(hash, 0, hashBytes, SaltSize, HashSize);
return Convert.ToBase64String(hashBytes);
}
public bool Verify(string providedPassword, string hashedPassword)
{
var hashBytes = Convert.FromBase64String(hashedPassword);
var salt = new byte[SaltSize];
Array.Copy(hashBytes, 0, salt, 0, SaltSize);
var storedHash = new byte[HashSize];
Array.Copy(hashBytes, SaltSize, storedHash, 0, HashSize);
var computedHash = Rfc2898DeriveBytes.Pbkdf2(
providedPassword,
salt,
Iterations,
HashAlgorithm,
HashSize
);
return CryptographicOperations.FixedTimeEquals(storedHash, computedHash);
}
}