using System.Security.Cryptography; using System.Text; using License.Api.Options; using Microsoft.Extensions.Options; namespace License.Api.Security; public class HmacSignatureService { private readonly SecurityOptions _options; public HmacSignatureService(IOptions options) { _options = options.Value; } public bool IsEnabled => _options.SignatureEnabled; public bool ValidateTimestamp(long timestamp) { var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); return Math.Abs(now - timestamp) <= _options.TimestampToleranceSeconds; } public string Sign(string payload, string secret) { using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret)); var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload)); return Convert.ToHexString(hash).ToLowerInvariant(); } public bool Verify(string payload, string signature, string secret) { if (string.IsNullOrWhiteSpace(signature)) return false; var expected = Sign(payload, secret); return string.Equals(signature, expected, StringComparison.OrdinalIgnoreCase); } }