feat: Implement DefaultCryptoHmac for compliance-aware HMAC operations

- Added DefaultCryptoHmac class implementing ICryptoHmac interface.
- Introduced purpose-based HMAC computation methods.
- Implemented verification methods for HMACs with constant-time comparison.
- Created HmacAlgorithms and HmacPurpose classes for well-known identifiers.
- Added compliance profile support for HMAC algorithms.
- Included asynchronous methods for HMAC computation from streams.
This commit is contained in:
StellaOps Bot
2025-12-06 00:41:04 +02:00
parent 43c281a8b2
commit f0662dd45f
362 changed files with 8441 additions and 22338 deletions

View File

@@ -1,8 +1,8 @@
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json.Serialization;
using StellaOps.Cryptography;
namespace StellaOps.ExportCenter.RiskBundles;
@@ -28,11 +28,13 @@ public sealed record RiskBundleManifestDsseSignature(
public sealed class HmacRiskBundleManifestSigner : IRiskBundleManifestSigner, IRiskBundleArchiveSigner
{
private const string DefaultPayloadType = "application/stellaops.risk-bundle.provider-manifest+json";
private readonly ICryptoHmac _cryptoHmac;
private readonly byte[] _key;
private readonly string _keyId;
public HmacRiskBundleManifestSigner(string key, string keyId)
public HmacRiskBundleManifestSigner(ICryptoHmac cryptoHmac, string key, string keyId)
{
_cryptoHmac = cryptoHmac ?? throw new ArgumentNullException(nameof(cryptoHmac));
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentException("Signing key cannot be empty.", nameof(key));
@@ -48,7 +50,7 @@ public sealed class HmacRiskBundleManifestSigner : IRiskBundleManifestSigner, IR
cancellationToken.ThrowIfCancellationRequested();
var pae = CreatePreAuthenticationEncoding(DefaultPayloadType, manifestJson);
var signature = ComputeHmac(pae, _key);
var signature = _cryptoHmac.ComputeHmacBase64ForPurpose(_key, pae, HmacPurpose.Signing);
var document = new RiskBundleManifestSignatureDocument(
DefaultPayloadType,
@@ -58,7 +60,7 @@ public sealed class HmacRiskBundleManifestSigner : IRiskBundleManifestSigner, IR
return Task.FromResult(document);
}
public Task<string> SignArchiveAsync(Stream archiveStream, CancellationToken cancellationToken = default)
public async Task<string> SignArchiveAsync(Stream archiveStream, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(archiveStream);
cancellationToken.ThrowIfCancellationRequested();
@@ -69,16 +71,8 @@ public sealed class HmacRiskBundleManifestSigner : IRiskBundleManifestSigner, IR
}
archiveStream.Position = 0;
using var hmac = new HMACSHA256(_key);
var signature = hmac.ComputeHash(archiveStream);
var signature = await _cryptoHmac.ComputeHmacForPurposeAsync(_key, archiveStream, HmacPurpose.Signing, cancellationToken);
archiveStream.Position = 0;
return Task.FromResult(Convert.ToBase64String(signature));
}
private static string ComputeHmac(byte[] pae, byte[] key)
{
using var hmac = new HMACSHA256(key);
var signature = hmac.ComputeHash(pae);
return Convert.ToBase64String(signature);
}

View File

@@ -9,9 +9,10 @@
<ItemGroup>
<ProjectReference Include="../StellaOps.ExportCenter/StellaOps.ExportCenter.Infrastructure/StellaOps.ExportCenter.Infrastructure.csproj" />
<ProjectReference Include="../StellaOps.ExportCenter/StellaOps.ExportCenter.Core/StellaOps.ExportCenter.Core.csproj" />
<ProjectReference Include="../../__Libraries/StellaOps.Cryptography/StellaOps.Cryptography.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
</ItemGroup>
</Project>