using System.Security.Cryptography; using StellaOps.AirGap.Time.Models; using StellaOps.AirGap.Time.Parsing; namespace StellaOps.AirGap.Time.Services; public sealed class Rfc3161Verifier : ITimeTokenVerifier { public TimeTokenFormat Format => TimeTokenFormat.Rfc3161; public TimeAnchorValidationResult Verify(ReadOnlySpan tokenBytes, IReadOnlyList trustRoots, out TimeAnchor anchor) { anchor = TimeAnchor.Unknown; if (trustRoots.Count == 0) { return TimeAnchorValidationResult.Failure("trust-roots-required"); } if (tokenBytes.IsEmpty) { return TimeAnchorValidationResult.Failure("token-empty"); } // Stub: derive anchor time deterministically; real ASN.1 verification to be added once trust roots finalized. var digestBytes = SHA256.HashData(tokenBytes); var digest = Convert.ToHexString(digestBytes).ToLowerInvariant(); var seconds = BitConverter.ToUInt64(digestBytes.AsSpan(0, 8)); var anchorTime = DateTimeOffset.UnixEpoch.AddSeconds(seconds % (3600 * 24 * 365)); anchor = new TimeAnchor(anchorTime, "rfc3161-token", "RFC3161", trustRoots[0].KeyId, digest); return TimeAnchorValidationResult.Success("rfc3161-stub-verified"); } }