using System.Text; using StellaOps.Provenance.Attestation; using Xunit; namespace StellaOps.Provenance.Attestation.Tests; public sealed class VerificationLibraryTests { [Fact] public async Task HmacVerifier_FailsWhenKeyExpired() { var key = new InMemoryKeyProvider("k1", Encoding.UTF8.GetBytes("secret"), DateTimeOffset.UtcNow.AddMinutes(-1)); var verifier = new HmacVerifier(key, new TestTimeProvider(DateTimeOffset.UtcNow)); var request = new SignRequest(Encoding.UTF8.GetBytes("payload"), "ct"); var signer = new HmacSigner(key, timeProvider: new TestTimeProvider(DateTimeOffset.UtcNow.AddMinutes(-2))); var signature = await signer.SignAsync(request); var result = await verifier.VerifyAsync(request, signature); Assert.False(result.IsValid); Assert.Contains("time", result.Reason); } [Fact] public async Task HmacVerifier_FailsWhenClockSkewTooLarge() { var now = new DateTimeOffset(2025, 11, 22, 12, 0, 0, TimeSpan.Zero); var key = new InMemoryKeyProvider("k", Encoding.UTF8.GetBytes("secret")); var signer = new HmacSigner(key, timeProvider: new TestTimeProvider(now.AddMinutes(10))); var request = new SignRequest(Encoding.UTF8.GetBytes("payload"), "ct"); var sig = await signer.SignAsync(request); var verifier = new HmacVerifier(key, new TestTimeProvider(now), TimeSpan.FromMinutes(5)); var result = await verifier.VerifyAsync(request, sig); Assert.False(result.IsValid); } [Fact] public void MerkleRootVerifier_DetectsMismatch() { var leaves = new[] { Encoding.UTF8.GetBytes("a"), Encoding.UTF8.GetBytes("b"), Encoding.UTF8.GetBytes("c") }; var expected = Convert.FromHexString("00"); var result = MerkleRootVerifier.VerifyRoot(leaves, expected, new TestTimeProvider(DateTimeOffset.UtcNow)); Assert.False(result.IsValid); Assert.Equal("merkle root mismatch", result.Reason); } [Fact] public void ChainOfCustodyVerifier_ComputesAggregate() { var hops = new[] { Encoding.UTF8.GetBytes("hop1"), Encoding.UTF8.GetBytes("hop2") }; using var sha = System.Security.Cryptography.SHA256.Create(); var aggregate = sha.ComputeHash(Array.Empty().Concat(hops[0]).ToArray()); aggregate = sha.ComputeHash(aggregate.Concat(hops[1]).ToArray()); var result = ChainOfCustodyVerifier.Verify(hops, aggregate, new TestTimeProvider(DateTimeOffset.UtcNow)); Assert.True(result.IsValid); } }