using System; using System.Linq; using System.Security.Cryptography; using System.Text; using Microsoft.Extensions.Options; namespace _0_Framework.Application; public class PasswordHasher : IPasswordHasher { private const int SaltSize = 16; // 128 bit private const int KeySize = 32; // 256 bit public PasswordHasher(IOptions options) { Options = options.Value; } private HashingOptions Options { get; } public string Hash(string password) { using var algorithm = new Rfc2898DeriveBytes(password, SaltSize, Options.Iterations, HashAlgorithmName.SHA256); var key = Convert.ToBase64String(algorithm.GetBytes(KeySize)); var salt = Convert.ToBase64String(algorithm.Salt); return $"{Options.Iterations}.{salt}.{key}"; } public (bool Verified, bool NeedsUpgrade) Check(string hash, string password) { var parts = hash.Split('.', 3); if (parts.Length != 3) { return (false, false); } var iterations = Convert.ToInt32(parts[0]); var salt = Convert.FromBase64String(parts[1]); var key = Convert.FromBase64String(parts[2]); var needsUpgrade = iterations != Options.Iterations; using var algorithm = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA256); var keyToCheck = algorithm.GetBytes(KeySize); var verified = keyToCheck.SequenceEqual(key); return (verified, needsUpgrade); } #region Mahan public string SlugHasher(long slug) { try { var test = slug.ToString(); UTF8Encoding encoder = new UTF8Encoding(); byte[] hashedDataBytes = encoder.GetBytes(test); return Convert.ToBase64String(hashedDataBytes); } catch { return ""; } } public long SlugDecrypt(string slug) { if (string.IsNullOrWhiteSpace(slug) || slug.Trim() == "0") { return 0; } try { byte[] bytes = Convert.FromBase64String(slug); string result = System.Text.Encoding.UTF8.GetString(bytes); return long.Parse(result); } catch { return -1; } } #endregion }