34 lines
1.1 KiB
C#
34 lines
1.1 KiB
C#
using System;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace SNote.Server.Security;
|
|
|
|
public static class PasswordHasher
|
|
{
|
|
private const int SaltSize = 16; // 128 bit
|
|
private const int KeySize = 32; // 256 bit
|
|
private const int Iterations = 10000;
|
|
|
|
public static string HashPassword(string password)
|
|
{
|
|
using var algorithm = new Rfc2898DeriveBytes(password, SaltSize, Iterations, HashAlgorithmName.SHA256);
|
|
var key = Convert.ToBase64String(algorithm.GetBytes(KeySize));
|
|
var salt = Convert.ToBase64String(algorithm.Salt);
|
|
return $"{Iterations}.{salt}.{key}";
|
|
}
|
|
|
|
public static bool VerifyPassword(string hash, string password)
|
|
{
|
|
var parts = hash.Split('.', 3);
|
|
if (parts.Length != 3) return false;
|
|
|
|
var iterations = int.Parse(parts[0]);
|
|
var salt = Convert.FromBase64String(parts[1]);
|
|
var key = Convert.FromBase64String(parts[2]);
|
|
|
|
using var algorithm = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA256);
|
|
var keyToCheck = algorithm.GetBytes(KeySize);
|
|
return CryptographicOperations.FixedTimeEquals(key, keyToCheck);
|
|
}
|
|
}
|