save progress

This commit is contained in:
StellaOps Bot
2026-01-02 15:52:31 +02:00
parent 2dec7e6a04
commit f46bde5575
174 changed files with 20793 additions and 8307 deletions

View File

@@ -48,7 +48,27 @@ public static class DsseEnvelopeExtensions
ArgumentNullException.ThrowIfNull(signatures);
var payloadBytes = Convert.FromBase64String(payloadBase64);
var dsseSignatures = signatures.Select(s => new DsseSignature(s.SignatureBase64, s.KeyId));
var dsseSignatures = new List<DsseSignature>();
var index = 0;
foreach (var signature in signatures)
{
if (string.IsNullOrWhiteSpace(signature.SignatureBase64))
{
throw new ArgumentException("Signature must be provided.", nameof(signatures));
}
try
{
Convert.FromBase64String(signature.SignatureBase64);
}
catch (FormatException ex)
{
throw new ArgumentException($"Signature at index {index} must be base64-encoded.", nameof(signatures), ex);
}
dsseSignatures.Add(new DsseSignature(signature.SignatureBase64, signature.KeyId));
index++;
}
return new DsseEnvelope(payloadType, payloadBytes, dsseSignatures);
}

View File

@@ -10,33 +10,42 @@ namespace StellaOps.Attestation;
public static class DsseHelper
{
private const string DefaultPayloadType = "https://in-toto.io/Statement/v1";
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web)
{
WriteIndented = false
};
public static byte[] PreAuthenticationEncoding(string payloadType, ReadOnlySpan<byte> payload)
{
static byte[] Cat(params byte[][] parts)
{
var len = 0;
foreach (var part in parts)
{
len += part.Length;
}
var buf = new byte[len];
var offset = 0;
foreach (var part in parts)
{
Buffer.BlockCopy(part, 0, buf, offset, part.Length);
offset += part.Length;
}
return buf;
}
var header = Encoding.UTF8.GetBytes("DSSEv1");
var pt = Encoding.UTF8.GetBytes(payloadType);
var lenPt = Encoding.UTF8.GetBytes(pt.Length.ToString(CultureInfo.InvariantCulture));
var lenPayload = Encoding.UTF8.GetBytes(payload.Length.ToString(CultureInfo.InvariantCulture));
var space = Encoding.UTF8.GetBytes(" ");
return Cat(header, space, lenPt, space, pt, space, lenPayload, space, payload.ToArray());
var totalLength = header.Length + space.Length + lenPt.Length + space.Length + pt.Length +
space.Length + lenPayload.Length + space.Length + payload.Length;
var buffer = new byte[totalLength];
var offset = 0;
static void CopyBytes(byte[] source, byte[] destination, ref int index)
{
Buffer.BlockCopy(source, 0, destination, index, source.Length);
index += source.Length;
}
CopyBytes(header, buffer, ref offset);
CopyBytes(space, buffer, ref offset);
CopyBytes(lenPt, buffer, ref offset);
CopyBytes(space, buffer, ref offset);
CopyBytes(pt, buffer, ref offset);
CopyBytes(space, buffer, ref offset);
CopyBytes(lenPayload, buffer, ref offset);
CopyBytes(space, buffer, ref offset);
payload.CopyTo(buffer.AsSpan(offset));
return buffer;
}
public static async Task<DsseEnvelope> WrapAsync(InTotoStatement statement, IAuthoritySigner signer, CancellationToken cancellationToken = default)
@@ -44,13 +53,13 @@ public static class DsseHelper
ArgumentNullException.ThrowIfNull(statement);
ArgumentNullException.ThrowIfNull(signer);
var payloadBytes = JsonSerializer.SerializeToUtf8Bytes(statement, statement.GetType());
var pae = PreAuthenticationEncoding(statement.Type ?? string.Empty, payloadBytes);
var payloadType = string.IsNullOrWhiteSpace(statement.Type) ? DefaultPayloadType : statement.Type;
var payloadBytes = JsonSerializer.SerializeToUtf8Bytes(statement, SerializerOptions);
var pae = PreAuthenticationEncoding(payloadType, payloadBytes);
var signatureBytes = await signer.SignAsync(pae, cancellationToken).ConfigureAwait(false);
var keyId = await signer.GetKeyIdAsync(cancellationToken).ConfigureAwait(false);
var dsseSignature = DsseSignature.FromBytes(signatureBytes, keyId);
var payloadType = statement.Type ?? "https://in-toto.io/Statement/v1";
return new DsseEnvelope(payloadType, payloadBytes, new[] { dsseSignature });
}
}

View File

@@ -3,7 +3,7 @@
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>

View File

@@ -7,4 +7,4 @@ Source of truth: `docs/implplan/SPRINT_20251229_049_BE_csproj_audit_maint_tests.
| --- | --- | --- |
| AUDIT-0043-M | DONE | Maintainability audit for StellaOps.Attestation. |
| AUDIT-0043-T | DONE | Test coverage audit for StellaOps.Attestation. |
| AUDIT-0043-A | TODO | Pending approval for changes. |
| AUDIT-0043-A | DONE | Applied DSSE payloadType alignment and base64 validation with tests. |