2026-01-13 02:47:34 +01:00
|
|
|
|
using System.Security.Cryptography;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using Konscious.Security.Cryptography;
|
2026-01-12 01:38:55 +01:00
|
|
|
|
|
2026-01-20 02:14:01 +01:00
|
|
|
|
namespace TimetableDesigner.Backend.Services.Authentication.Core.Helpers;
|
2026-01-13 02:47:34 +01:00
|
|
|
|
|
|
|
|
|
|
public class PasswordHasher : IPasswordHasher
|
2026-01-12 01:38:55 +01:00
|
|
|
|
{
|
2026-01-13 02:47:34 +01:00
|
|
|
|
private const string RandomPasswordCharacters = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890!@#$%^&*()-_=+[{]};:'\"\\|,<.>/?";
|
|
|
|
|
|
|
|
|
|
|
|
public PasswordHashData CreateHash(string password)
|
|
|
|
|
|
{
|
|
|
|
|
|
string salt = RandomNumberGenerator.GetString(RandomPasswordCharacters, 20);
|
|
|
|
|
|
byte[] hash = ComputeHash(password, salt);
|
|
|
|
|
|
PasswordHashData data = new PasswordHashData(hash, salt);
|
|
|
|
|
|
return data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool ValidatePassword(PasswordHashData hash, string password)
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] actualHash = hash.Hash;
|
|
|
|
|
|
byte[] checkedHash = ComputeHash(password, hash.Salt);
|
|
|
|
|
|
bool checkResult = checkedHash.SequenceEqual(actualHash);
|
|
|
|
|
|
return checkResult;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected byte[] ComputeHash(string password, string salt)
|
|
|
|
|
|
{
|
|
|
|
|
|
Argon2id hashFunction = new Argon2id(Encoding.UTF8.GetBytes(password))
|
|
|
|
|
|
{
|
|
|
|
|
|
Salt = Encoding.UTF8.GetBytes(salt),
|
|
|
|
|
|
DegreeOfParallelism = 8,
|
|
|
|
|
|
MemorySize = 65536,
|
|
|
|
|
|
Iterations = 4
|
|
|
|
|
|
};
|
|
|
|
|
|
byte[] hash = hashFunction.GetBytes(32);
|
|
|
|
|
|
return hash;
|
|
|
|
|
|
}
|
2026-01-12 01:38:55 +01:00
|
|
|
|
}
|