40 lines
1.3 KiB
C#
40 lines
1.3 KiB
C#
using System.Security.Cryptography;
|
|
|
|
namespace KronaStaffTerminal.Services;
|
|
|
|
public static class AdminPinService
|
|
{
|
|
public const int CurrentIterations = 600_000;
|
|
|
|
public static (string Salt, string Hash, int Iterations) Hash(string pin)
|
|
{
|
|
var salt = RandomNumberGenerator.GetBytes(16);
|
|
var hash = Rfc2898DeriveBytes.Pbkdf2(pin, salt, CurrentIterations, HashAlgorithmName.SHA256, 32);
|
|
return (Convert.ToBase64String(salt), Convert.ToBase64String(hash), CurrentIterations);
|
|
}
|
|
|
|
public static bool Verify(string pin, string saltBase64, string hashBase64, int iterations)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(pin) || string.IsNullOrWhiteSpace(saltBase64) || string.IsNullOrWhiteSpace(hashBase64))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
var salt = Convert.FromBase64String(saltBase64);
|
|
var expected = Convert.FromBase64String(hashBase64);
|
|
var actual = Rfc2898DeriveBytes.Pbkdf2(
|
|
pin,
|
|
salt,
|
|
Math.Clamp(iterations, 120_000, CurrentIterations),
|
|
HashAlgorithmName.SHA256,
|
|
expected.Length);
|
|
return CryptographicOperations.FixedTimeEquals(actual, expected);
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|