44 lines
1.4 KiB
C#
44 lines
1.4 KiB
C#
using System.Security.Cryptography;
|
|
|
|
namespace LingAdmin.API.Services;
|
|
|
|
public class PasswordHasher : IPasswordHasher
|
|
{
|
|
private const int SaltSize = 16; // 128 bit
|
|
private const int KeySize = 32; // 256 bit
|
|
private const int Iterations = 10000;
|
|
private static readonly HashAlgorithmName Algorithm = HashAlgorithmName.SHA256;
|
|
|
|
public string HashPassword(string password)
|
|
{
|
|
var salt = RandomNumberGenerator.GetBytes(SaltSize);
|
|
var hash = Rfc2898DeriveBytes.Pbkdf2(password, salt, Iterations, Algorithm, KeySize);
|
|
|
|
// Combine salt and hash
|
|
var result = new byte[SaltSize + KeySize];
|
|
Buffer.BlockCopy(salt, 0, result, 0, SaltSize);
|
|
Buffer.BlockCopy(hash, 0, result, SaltSize, KeySize);
|
|
|
|
return Convert.ToBase64String(result);
|
|
}
|
|
|
|
public bool VerifyPassword(string password, string passwordHash)
|
|
{
|
|
var hashBytes = Convert.FromBase64String(passwordHash);
|
|
|
|
// Extract salt
|
|
var salt = new byte[SaltSize];
|
|
Buffer.BlockCopy(hashBytes, 0, salt, 0, SaltSize);
|
|
|
|
// Extract hash
|
|
var hash = new byte[KeySize];
|
|
Buffer.BlockCopy(hashBytes, SaltSize, hash, 0, KeySize);
|
|
|
|
// Compute hash with the extracted salt
|
|
var computedHash = Rfc2898DeriveBytes.Pbkdf2(password, salt, Iterations, Algorithm, KeySize);
|
|
|
|
// Compare hashes
|
|
return CryptographicOperations.FixedTimeEquals(hash, computedHash);
|
|
}
|
|
}
|