save progress
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using StellaOps.Attestation;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
|
||||
namespace StellaOps.Attestation.Tests;
|
||||
|
||||
public sealed class DsseEnvelopeExtensionsTests
|
||||
{
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void FromBase64_RoundTripsPayloadAndSignature()
|
||||
{
|
||||
var payloadBytes = Encoding.UTF8.GetBytes("{}");
|
||||
var payloadBase64 = Convert.ToBase64String(payloadBytes);
|
||||
var signatureBase64 = Convert.ToBase64String(Convert.FromHexString("deadbeef"));
|
||||
|
||||
var envelope = DsseEnvelopeExtensions.FromBase64(
|
||||
"example/type",
|
||||
payloadBase64,
|
||||
new (string? KeyId, string SignatureBase64)[] { (KeyId: "key-1", SignatureBase64: signatureBase64) });
|
||||
|
||||
Assert.Equal(payloadBase64, envelope.GetPayloadBase64());
|
||||
Assert.Single(envelope.Signatures);
|
||||
Assert.Equal("key-1", envelope.Signatures[0].KeyId);
|
||||
Assert.Equal(signatureBase64, envelope.Signatures[0].Signature);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void FromBase64_ThrowsOnInvalidSignatureBase64()
|
||||
{
|
||||
var payloadBytes = Encoding.UTF8.GetBytes("{}");
|
||||
var payloadBase64 = Convert.ToBase64String(payloadBytes);
|
||||
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
DsseEnvelopeExtensions.FromBase64(
|
||||
"example/type",
|
||||
payloadBase64,
|
||||
new (string? KeyId, string SignatureBase64)[] { (KeyId: "key-1", SignatureBase64: "not-base64") }));
|
||||
|
||||
Assert.Contains("base64", ex.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
@@ -15,24 +15,30 @@ public class DsseHelperTests
|
||||
{
|
||||
private sealed class FakeSigner : IAuthoritySigner
|
||||
{
|
||||
public byte[]? LastPayload { get; private set; }
|
||||
|
||||
public Task<string> GetKeyIdAsync(System.Threading.CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult("fake-key");
|
||||
|
||||
public Task<byte[]> SignAsync(ReadOnlyMemory<byte> paePayload, System.Threading.CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(Convert.FromHexString("deadbeef"));
|
||||
{
|
||||
LastPayload = paePayload.ToArray();
|
||||
return Task.FromResult(Convert.FromHexString("deadbeef"));
|
||||
}
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task WrapAsync_ProducesDsseEnvelope()
|
||||
{
|
||||
var signer = new FakeSigner();
|
||||
var stmt = new InTotoStatement(
|
||||
Type: "https://in-toto.io/Statement/v1",
|
||||
Subject: new[] { new Subject("demo", new System.Collections.Generic.Dictionary<string, string> { { "sha256", "abcd" } }) },
|
||||
PredicateType: "demo/predicate",
|
||||
Predicate: new { hello = "world" });
|
||||
|
||||
var envelope = await DsseHelper.WrapAsync(stmt, new FakeSigner());
|
||||
var envelope = await DsseHelper.WrapAsync(stmt, signer, TestContext.Current.CancellationToken);
|
||||
|
||||
envelope.PayloadType.Should().Be("https://in-toto.io/Statement/v1");
|
||||
var roundtrip = JsonSerializer.Deserialize<InTotoStatement>(envelope.Payload.Span);
|
||||
@@ -51,9 +57,27 @@ public class DsseHelperTests
|
||||
|
||||
var pae = DsseHelper.PreAuthenticationEncoding(payloadType, payload);
|
||||
|
||||
// Verify PAE contains expected components (payload type and payload)
|
||||
var paeString = Encoding.UTF8.GetString(pae);
|
||||
paeString.Should().Contain(payloadType);
|
||||
paeString.Should().Contain("{}");
|
||||
var expected = Encoding.UTF8.GetBytes($"DSSEv1 {payloadType.Length} {payloadType} {payload.Length} {{}}");
|
||||
pae.Should().Equal(expected);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task WrapAsync_UsesDefaultPayloadTypeWhenMissing()
|
||||
{
|
||||
var signer = new FakeSigner();
|
||||
var stmt = new InTotoStatement(
|
||||
Type: "",
|
||||
Subject: new[] { new Subject("demo", new System.Collections.Generic.Dictionary<string, string> { { "sha256", "abcd" } }) },
|
||||
PredicateType: "demo/predicate",
|
||||
Predicate: new { hello = "world" });
|
||||
|
||||
var envelope = await DsseHelper.WrapAsync(stmt, signer, TestContext.Current.CancellationToken);
|
||||
|
||||
envelope.PayloadType.Should().Be("https://in-toto.io/Statement/v1");
|
||||
signer.LastPayload.Should().NotBeNull();
|
||||
var expectedPayload = JsonSerializer.SerializeToUtf8Bytes(stmt, new JsonSerializerOptions(JsonSerializerDefaults.Web) { WriteIndented = false });
|
||||
var expectedPae = DsseHelper.PreAuthenticationEncoding(envelope.PayloadType, expectedPayload);
|
||||
signer.LastPayload!.Should().Equal(expectedPae);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user