using System.Globalization; using System.Security.Cryptography; using System.Text; namespace SeaHaven.Services.Helpers { /// /// Generation and hashing for emailed password reset codes. The raw code exists /// only in memory and in the email sent to the account holder. /// public static class PasswordResetCodeSecrets { public static string NewCode() { return RandomNumberGenerator.GetInt32(0, 1_000_000).ToString("D6", CultureInfo.InvariantCulture); } public static string NewSalt() { return Convert.ToHexString(RandomNumberGenerator.GetBytes(16)).ToLowerInvariant(); } public static string Hash(string salt, string code) { ArgumentNullException.ThrowIfNull(salt); ArgumentNullException.ThrowIfNull(code); return Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(salt + ":" + code))).ToLowerInvariant(); } public static bool Matches(string salt, string candidate, string expectedHash) { if (string.IsNullOrEmpty(salt) || string.IsNullOrEmpty(expectedHash)) return false; var actual = Encoding.ASCII.GetBytes(Hash(salt, candidate.Trim())); var expected = Encoding.ASCII.GetBytes(expectedHash); return CryptographicOperations.FixedTimeEquals(actual, expected); } } }