up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled

This commit is contained in:
master
2025-11-27 15:05:48 +02:00
parent 4831c7fcb0
commit e950474a77
278 changed files with 81498 additions and 672 deletions

View File

@@ -1,5 +1,5 @@
using System.Security.Cryptography;
using System.Text;
using StellaOps.Cryptography;
namespace StellaOps.EvidenceLocker.Core.Builders;
@@ -10,6 +10,35 @@ public interface IMerkleTreeCalculator
public sealed class MerkleTreeCalculator : IMerkleTreeCalculator
{
private readonly ICryptoHasher _hasher;
/// <summary>
/// Creates a MerkleTreeCalculator using the specified hasher.
/// </summary>
/// <param name="hasher">Crypto hasher resolved from the provider registry.</param>
public MerkleTreeCalculator(ICryptoHasher hasher)
{
_hasher = hasher ?? throw new ArgumentNullException(nameof(hasher));
}
/// <summary>
/// Creates a MerkleTreeCalculator using the crypto registry to resolve the hasher.
/// </summary>
/// <param name="cryptoRegistry">Crypto provider registry.</param>
/// <param name="algorithmId">Hash algorithm to use (defaults to SHA256).</param>
/// <param name="preferredProvider">Optional preferred crypto provider.</param>
public MerkleTreeCalculator(
ICryptoProviderRegistry cryptoRegistry,
string? algorithmId = null,
string? preferredProvider = null)
{
ArgumentNullException.ThrowIfNull(cryptoRegistry);
var algorithm = algorithmId ?? HashAlgorithms.Sha256;
var resolution = cryptoRegistry.ResolveHasher(algorithm, preferredProvider);
_hasher = resolution.Hasher;
}
public string CalculateRootHash(IEnumerable<string> canonicalLeafValues)
{
var leaves = canonicalLeafValues
@@ -24,7 +53,7 @@ public sealed class MerkleTreeCalculator : IMerkleTreeCalculator
return BuildTree(leaves);
}
private static string BuildTree(IReadOnlyList<string> currentLevel)
private string BuildTree(IReadOnlyList<string> currentLevel)
{
if (currentLevel.Count == 1)
{
@@ -45,10 +74,9 @@ public sealed class MerkleTreeCalculator : IMerkleTreeCalculator
return BuildTree(nextLevel);
}
private static string HashString(string value)
private string HashString(string value)
{
var bytes = Encoding.UTF8.GetBytes(value);
var hash = SHA256.HashData(bytes);
return Convert.ToHexString(hash).ToLowerInvariant();
return _hasher.ComputeHashHex(bytes);
}
}

View File

@@ -24,6 +24,11 @@ public sealed class EvidenceLockerOptions
public PortableOptions Portable { get; init; } = new();
public IncidentModeOptions Incident { get; init; } = new();
/// <summary>
/// Cryptographic options for hash algorithm selection and provider routing.
/// </summary>
public EvidenceCryptoOptions Crypto { get; init; } = new();
}
public sealed class DatabaseOptions
@@ -208,3 +213,20 @@ public sealed class PortableOptions
[MinLength(1)]
public string MetadataFileName { get; init; } = "bundle.json";
}
/// <summary>
/// Cryptographic options for evidence bundle hashing and provider routing.
/// </summary>
public sealed class EvidenceCryptoOptions
{
/// <summary>
/// Hash algorithm used for Merkle tree computation. Defaults to SHA256.
/// Supported: SHA256, SHA384, SHA512, GOST3411-2012-256, GOST3411-2012-512.
/// </summary>
public string HashAlgorithm { get; init; } = HashAlgorithms.Sha256;
/// <summary>
/// Preferred crypto provider name. When null, the registry uses its default resolution order.
/// </summary>
public string? PreferredProvider { get; init; }
}

View File

@@ -8,6 +8,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using StellaOps.Cryptography;
using StellaOps.Cryptography.DependencyInjection;
using StellaOps.Cryptography.Plugin.BouncyCastle;
using StellaOps.EvidenceLocker.Core.Builders;
@@ -61,7 +62,15 @@ public static class EvidenceLockerInfrastructureServiceCollectionExtensions
services.AddSingleton<IEvidenceLockerMigrationRunner, EvidenceLockerMigrationRunner>();
services.AddHostedService<EvidenceLockerMigrationHostedService>();
services.AddSingleton<IMerkleTreeCalculator, MerkleTreeCalculator>();
services.AddSingleton<IMerkleTreeCalculator>(provider =>
{
var options = provider.GetRequiredService<IOptions<EvidenceLockerOptions>>().Value;
var cryptoRegistry = provider.GetRequiredService<ICryptoProviderRegistry>();
return new MerkleTreeCalculator(
cryptoRegistry,
options.Crypto.HashAlgorithm,
options.Crypto.PreferredProvider);
});
services.AddScoped<IEvidenceBundleBuilder, EvidenceBundleBuilder>();
services.AddScoped<IEvidenceBundleRepository, EvidenceBundleRepository>();