up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
sm-remote-ci / build-and-test (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-12-15 09:51:11 +02:00
parent 41864227d2
commit b1f40945b7
44 changed files with 2368 additions and 31 deletions

View File

@@ -0,0 +1,118 @@
using StellaOps.Cryptography;
namespace StellaOps.Audit.ReplayToken.Tests;
public sealed class ReplayTokenGeneratorTests
{
[Fact]
public void Generate_SameInputs_ReturnsSameValue()
{
var cryptoHash = DefaultCryptoHash.CreateForTests();
var fixedNow = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero);
var timeProvider = new FixedTimeProvider(fixedNow);
var generator = new Sha256ReplayTokenGenerator(cryptoHash, timeProvider);
var request = new ReplayTokenRequest
{
FeedManifests = new[] { "sha256:bbb", "sha256:aaa" },
RulesVersion = "rules-v1",
RulesHash = "sha256:rules",
LatticePolicyVersion = "lattice-v1",
LatticePolicyHash = "sha256:lattice",
InputHashes = new[] { "sha256:input2", "sha256:input1" },
ScoringConfigVersion = "score-v1",
EvidenceHashes = new[] { "sha256:e2", "sha256:e1" },
AdditionalContext = new Dictionary<string, string>
{
["b"] = "2",
["a"] = "1"
}
};
var token1 = generator.Generate(request);
var token2 = generator.Generate(request);
Assert.Equal(token1.Value, token2.Value);
Assert.Equal(token1.Canonical, token2.Canonical);
}
[Fact]
public void Generate_IgnoresArrayOrdering()
{
var cryptoHash = DefaultCryptoHash.CreateForTests();
var timeProvider = new FixedTimeProvider(new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero));
var generator = new Sha256ReplayTokenGenerator(cryptoHash, timeProvider);
var requestA = new ReplayTokenRequest
{
FeedManifests = new[] { "sha256:aaa", "sha256:bbb" },
InputHashes = new[] { "sha256:input1", "sha256:input2" }
};
var requestB = new ReplayTokenRequest
{
FeedManifests = new[] { "sha256:bbb", "sha256:aaa" },
InputHashes = new[] { "sha256:input2", "sha256:input1" }
};
var tokenA = generator.Generate(requestA);
var tokenB = generator.Generate(requestB);
Assert.Equal(tokenA.Value, tokenB.Value);
}
[Fact]
public void Verify_MatchingInputs_ReturnsTrue()
{
var cryptoHash = DefaultCryptoHash.CreateForTests();
var timeProvider = new FixedTimeProvider(new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero));
var generator = new Sha256ReplayTokenGenerator(cryptoHash, timeProvider);
var request = new ReplayTokenRequest { InputHashes = new[] { "sha256:input" } };
var token = generator.Generate(request);
Assert.True(generator.Verify(token, request));
}
[Fact]
public void Verify_DifferentInputs_ReturnsFalse()
{
var cryptoHash = DefaultCryptoHash.CreateForTests();
var timeProvider = new FixedTimeProvider(new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero));
var generator = new Sha256ReplayTokenGenerator(cryptoHash, timeProvider);
var request = new ReplayTokenRequest { InputHashes = new[] { "sha256:input" } };
var different = new ReplayTokenRequest { InputHashes = new[] { "sha256:other" } };
var token = generator.Generate(request);
Assert.False(generator.Verify(token, different));
}
[Fact]
public void ReplayToken_Parse_RoundTripsCanonical()
{
var token = new ReplayToken("0123456789abcdef", DateTimeOffset.UnixEpoch);
var parsed = ReplayToken.Parse(token.Canonical);
Assert.Equal(token.Value, parsed.Value);
Assert.Equal(token.Algorithm, parsed.Algorithm);
Assert.Equal(token.Version, parsed.Version);
}
[Theory]
[InlineData("")]
[InlineData("replay")]
[InlineData("replay:v1.0:SHA-256")]
[InlineData("other:v1.0:SHA-256:abc")]
public void ReplayToken_Parse_Invalid_Throws(string canonical)
{
Assert.ThrowsAny<Exception>(() => ReplayToken.Parse(canonical));
}
private sealed class FixedTimeProvider(DateTimeOffset now) : TimeProvider
{
public override DateTimeOffset GetUtcNow() => now;
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" ?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>preview</LangVersion>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\\..\\__Libraries\\StellaOps.Audit.ReplayToken\\StellaOps.Audit.ReplayToken.csproj" />
</ItemGroup>
</Project>