- Add RateLimitConfig for configuration management with YAML binding support. - Introduce RateLimitDecision to encapsulate the result of rate limit checks. - Implement RateLimitMetrics for OpenTelemetry metrics tracking. - Create RateLimitMiddleware for enforcing rate limits on incoming requests. - Develop RateLimitService to orchestrate instance and environment rate limit checks. - Add RateLimitServiceCollectionExtensions for dependency injection registration.
266 lines
7.8 KiB
C#
266 lines
7.8 KiB
C#
// -----------------------------------------------------------------------------
|
|
// VerificationPipelineBenchmarks.cs
|
|
// Sprint: SPRINT_0501_0001_0001_proof_evidence_chain_master
|
|
// Task: PROOF-MASTER-0005
|
|
// Description: Benchmarks for verification pipeline operations
|
|
// -----------------------------------------------------------------------------
|
|
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using BenchmarkDotNet.Attributes;
|
|
|
|
namespace StellaOps.Bench.ProofChain.Benchmarks;
|
|
|
|
/// <summary>
|
|
/// Benchmarks for verification pipeline operations.
|
|
/// Target: Full verification < 50ms typical.
|
|
/// </summary>
|
|
[MemoryDiagnoser]
|
|
[SimpleJob(warmupCount: 3, iterationCount: 10)]
|
|
public class VerificationPipelineBenchmarks
|
|
{
|
|
private TestProofBundle _bundle = null!;
|
|
private byte[] _dsseEnvelope = null!;
|
|
private List<byte[]> _merkleProof = null!;
|
|
|
|
[GlobalSetup]
|
|
public void Setup()
|
|
{
|
|
// Create a realistic test bundle
|
|
var statements = Enumerable.Range(0, 5)
|
|
.Select(i => new TestStatement
|
|
{
|
|
StatementId = GenerateId(),
|
|
PredicateType = "evidence.stella/v1",
|
|
Payload = GenerateRandomBytes(1024)
|
|
})
|
|
.ToList();
|
|
|
|
var envelopes = statements.Select(s => new TestEnvelope
|
|
{
|
|
PayloadType = "application/vnd.in-toto+json",
|
|
Payload = s.Payload,
|
|
Signature = GenerateRandomBytes(64),
|
|
KeyId = "test-key-1"
|
|
}).ToList();
|
|
|
|
_bundle = new TestProofBundle
|
|
{
|
|
BundleId = GenerateId(),
|
|
Statements = statements,
|
|
Envelopes = envelopes,
|
|
MerkleRoot = GenerateRandomBytes(32),
|
|
LogIndex = 12345,
|
|
InclusionProof = Enumerable.Range(0, 10).Select(_ => GenerateRandomBytes(32)).ToList()
|
|
};
|
|
|
|
// DSSE envelope for signature verification
|
|
_dsseEnvelope = JsonSerializer.SerializeToUtf8Bytes(new
|
|
{
|
|
payloadType = "application/vnd.in-toto+json",
|
|
payload = Convert.ToBase64String(GenerateRandomBytes(1024)),
|
|
signatures = new[]
|
|
{
|
|
new { keyid = "key-1", sig = Convert.ToBase64String(GenerateRandomBytes(64)) }
|
|
}
|
|
});
|
|
|
|
// Merkle proof (typical depth ~20 for large trees)
|
|
_merkleProof = Enumerable.Range(0, 20)
|
|
.Select(_ => GenerateRandomBytes(32))
|
|
.ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// DSSE signature verification (crypto operation).
|
|
/// Target: < 5ms per envelope.
|
|
/// </summary>
|
|
[Benchmark]
|
|
public bool VerifyDsseSignature()
|
|
{
|
|
// Simulate signature verification (actual crypto would use ECDsa)
|
|
foreach (var envelope in _bundle.Envelopes)
|
|
{
|
|
var payloadHash = SHA256.HashData(envelope.Payload);
|
|
// In real impl, verify signature against public key
|
|
_ = SHA256.HashData(envelope.Signature);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// ID recomputation verification.
|
|
/// Target: < 2ms per bundle.
|
|
/// </summary>
|
|
[Benchmark]
|
|
public bool VerifyIdRecomputation()
|
|
{
|
|
foreach (var statement in _bundle.Statements)
|
|
{
|
|
var recomputedId = $"sha256:{Convert.ToHexString(SHA256.HashData(statement.Payload)).ToLowerInvariant()}";
|
|
if (!statement.StatementId.Equals(recomputedId, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
// IDs won't match in this benchmark, but we simulate the work
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Merkle proof verification.
|
|
/// Target: < 1ms per proof.
|
|
/// </summary>
|
|
[Benchmark]
|
|
public bool VerifyMerkleProof()
|
|
{
|
|
var leafHash = SHA256.HashData(_bundle.Statements[0].Payload);
|
|
var current = leafHash;
|
|
|
|
foreach (var sibling in _merkleProof)
|
|
{
|
|
var combined = new byte[64];
|
|
if (current[0] < sibling[0])
|
|
{
|
|
current.CopyTo(combined, 0);
|
|
sibling.CopyTo(combined, 32);
|
|
}
|
|
else
|
|
{
|
|
sibling.CopyTo(combined, 0);
|
|
current.CopyTo(combined, 32);
|
|
}
|
|
current = SHA256.HashData(combined);
|
|
}
|
|
|
|
return current.SequenceEqual(_bundle.MerkleRoot);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rekor inclusion proof verification (simulated).
|
|
/// Target: < 10ms (cached STH).
|
|
/// </summary>
|
|
[Benchmark]
|
|
public bool VerifyRekorInclusion()
|
|
{
|
|
// Simulate Rekor verification:
|
|
// 1. Verify entry hash
|
|
var entryHash = SHA256.HashData(JsonSerializer.SerializeToUtf8Bytes(_bundle));
|
|
|
|
// 2. Verify inclusion proof against STH
|
|
return VerifyMerkleProof();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Trust anchor key lookup.
|
|
/// Target: < 500μs.
|
|
/// </summary>
|
|
[Benchmark]
|
|
public bool VerifyKeyTrust()
|
|
{
|
|
// Simulate trust anchor lookup
|
|
var trustedKeys = new HashSet<string> { "test-key-1", "test-key-2", "test-key-3" };
|
|
|
|
foreach (var envelope in _bundle.Envelopes)
|
|
{
|
|
if (!trustedKeys.Contains(envelope.KeyId))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Full verification pipeline.
|
|
/// Target: < 50ms typical.
|
|
/// </summary>
|
|
[Benchmark]
|
|
public VerificationResult FullVerification()
|
|
{
|
|
var steps = new List<StepResult>();
|
|
|
|
// Step 1: DSSE signatures
|
|
var dsseValid = VerifyDsseSignature();
|
|
steps.Add(new StepResult { Step = "dsse", Passed = dsseValid });
|
|
|
|
// Step 2: ID recomputation
|
|
var idsValid = VerifyIdRecomputation();
|
|
steps.Add(new StepResult { Step = "ids", Passed = idsValid });
|
|
|
|
// Step 3: Merkle proof
|
|
var merkleValid = VerifyMerkleProof();
|
|
steps.Add(new StepResult { Step = "merkle", Passed = merkleValid });
|
|
|
|
// Step 4: Rekor inclusion
|
|
var rekorValid = VerifyRekorInclusion();
|
|
steps.Add(new StepResult { Step = "rekor", Passed = rekorValid });
|
|
|
|
// Step 5: Trust anchor
|
|
var trustValid = VerifyKeyTrust();
|
|
steps.Add(new StepResult { Step = "trust", Passed = trustValid });
|
|
|
|
return new VerificationResult
|
|
{
|
|
IsValid = steps.All(s => s.Passed),
|
|
Steps = steps
|
|
};
|
|
}
|
|
|
|
#region Helpers
|
|
|
|
private static string GenerateId()
|
|
{
|
|
var hash = GenerateRandomBytes(32);
|
|
return $"sha256:{Convert.ToHexString(hash).ToLowerInvariant()}";
|
|
}
|
|
|
|
private static byte[] GenerateRandomBytes(int length)
|
|
{
|
|
var bytes = new byte[length];
|
|
RandomNumberGenerator.Fill(bytes);
|
|
return bytes;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
#region Test Types
|
|
|
|
internal sealed class TestProofBundle
|
|
{
|
|
public required string BundleId { get; init; }
|
|
public required List<TestStatement> Statements { get; init; }
|
|
public required List<TestEnvelope> Envelopes { get; init; }
|
|
public required byte[] MerkleRoot { get; init; }
|
|
public required long LogIndex { get; init; }
|
|
public required List<byte[]> InclusionProof { get; init; }
|
|
}
|
|
|
|
internal sealed class TestStatement
|
|
{
|
|
public required string StatementId { get; init; }
|
|
public required string PredicateType { get; init; }
|
|
public required byte[] Payload { get; init; }
|
|
}
|
|
|
|
internal sealed class TestEnvelope
|
|
{
|
|
public required string PayloadType { get; init; }
|
|
public required byte[] Payload { get; init; }
|
|
public required byte[] Signature { get; init; }
|
|
public required string KeyId { get; init; }
|
|
}
|
|
|
|
internal sealed class VerificationResult
|
|
{
|
|
public required bool IsValid { get; init; }
|
|
public required List<StepResult> Steps { get; init; }
|
|
}
|
|
|
|
internal sealed class StepResult
|
|
{
|
|
public required string Step { get; init; }
|
|
public required bool Passed { get; init; }
|
|
}
|
|
|
|
#endregion
|