Files
git.stella-ops.org/src/__Libraries/StellaOps.Cryptography/ComplianceProfiles.cs
StellaOps Bot f0662dd45f 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.
2025-12-06 00:41:04 +02:00

289 lines
12 KiB
C#

namespace StellaOps.Cryptography;
/// <summary>
/// Built-in compliance profiles for different jurisdictional crypto requirements.
/// </summary>
public static class ComplianceProfiles
{
/// <summary>
/// Default/World profile using BLAKE3 for graph hashing, SHA-256 for everything else.
/// Suitable for international deployments without specific compliance requirements.
/// </summary>
public static readonly ComplianceProfile World = new()
{
ProfileId = "world",
StandardName = "ISO/Default",
Description = "Default profile using BLAKE3 for graph content-addressing, SHA-256 for symbol/content hashing.",
PurposeAlgorithms = new Dictionary<string, string>
{
[HashPurpose.Graph] = HashAlgorithms.Blake3_256,
[HashPurpose.Symbol] = HashAlgorithms.Sha256,
[HashPurpose.Content] = HashAlgorithms.Sha256,
[HashPurpose.Merkle] = HashAlgorithms.Sha256,
[HashPurpose.Attestation] = HashAlgorithms.Sha256,
[HashPurpose.Interop] = HashAlgorithms.Sha256,
[HashPurpose.Secret] = PasswordHashAlgorithms.Argon2id,
},
HashPrefixes = new Dictionary<string, string>
{
[HashPurpose.Graph] = "blake3:",
[HashPurpose.Symbol] = "sha256:",
[HashPurpose.Content] = "sha256:",
[HashPurpose.Merkle] = "sha256:",
[HashPurpose.Attestation] = "sha256:",
[HashPurpose.Interop] = "sha256:",
[HashPurpose.Secret] = "argon2id:",
},
HmacPurposeAlgorithms = new Dictionary<string, string>
{
[HmacPurpose.Signing] = HmacAlgorithms.HmacSha256,
[HmacPurpose.Authentication] = HmacAlgorithms.HmacSha256,
[HmacPurpose.WebhookInterop] = HmacAlgorithms.HmacSha256,
},
AllowInteropOverride = true,
};
/// <summary>
/// FIPS 140-3 (US Federal) compliance profile.
/// Uses only FIPS-approved algorithms: SHA-256, SHA-384, SHA-512, PBKDF2.
/// Note: BLAKE3 is not FIPS-approved, so SHA-256 is used for graph hashing.
/// </summary>
public static readonly ComplianceProfile Fips = new()
{
ProfileId = "fips",
StandardName = "FIPS 140-3",
Description = "US Federal Information Processing Standard 140-3. Uses only FIPS-approved algorithms.",
PurposeAlgorithms = new Dictionary<string, string>
{
[HashPurpose.Graph] = HashAlgorithms.Sha256, // BLAKE3 not FIPS-approved
[HashPurpose.Symbol] = HashAlgorithms.Sha256,
[HashPurpose.Content] = HashAlgorithms.Sha256,
[HashPurpose.Merkle] = HashAlgorithms.Sha256,
[HashPurpose.Attestation] = HashAlgorithms.Sha256,
[HashPurpose.Interop] = HashAlgorithms.Sha256,
[HashPurpose.Secret] = PasswordHashAlgorithms.Pbkdf2Sha256,
},
HashPrefixes = new Dictionary<string, string>
{
[HashPurpose.Graph] = "sha256:",
[HashPurpose.Symbol] = "sha256:",
[HashPurpose.Content] = "sha256:",
[HashPurpose.Merkle] = "sha256:",
[HashPurpose.Attestation] = "sha256:",
[HashPurpose.Interop] = "sha256:",
[HashPurpose.Secret] = "pbkdf2:",
},
HmacPurposeAlgorithms = new Dictionary<string, string>
{
[HmacPurpose.Signing] = HmacAlgorithms.HmacSha256,
[HmacPurpose.Authentication] = HmacAlgorithms.HmacSha256,
[HmacPurpose.WebhookInterop] = HmacAlgorithms.HmacSha256,
},
AllowInteropOverride = true,
};
/// <summary>
/// GOST R 34.11-2012 (Russian) compliance profile.
/// Uses GOST Stribog hash for all purposes except Interop (which remains SHA-256 for external compatibility).
/// </summary>
public static readonly ComplianceProfile Gost = new()
{
ProfileId = "gost",
StandardName = "GOST R 34.11-2012",
Description = "Russian GOST R 34.11-2012 (Stribog) hash standard. Interop uses SHA-256 for external tool compatibility.",
PurposeAlgorithms = new Dictionary<string, string>
{
[HashPurpose.Graph] = HashAlgorithms.Gost3411_2012_256,
[HashPurpose.Symbol] = HashAlgorithms.Gost3411_2012_256,
[HashPurpose.Content] = HashAlgorithms.Gost3411_2012_256,
[HashPurpose.Merkle] = HashAlgorithms.Gost3411_2012_256,
[HashPurpose.Attestation] = HashAlgorithms.Gost3411_2012_256,
[HashPurpose.Interop] = HashAlgorithms.Sha256, // Override for external compatibility
[HashPurpose.Secret] = PasswordHashAlgorithms.Argon2id,
},
HashPrefixes = new Dictionary<string, string>
{
[HashPurpose.Graph] = "gost3411:",
[HashPurpose.Symbol] = "gost3411:",
[HashPurpose.Content] = "gost3411:",
[HashPurpose.Merkle] = "gost3411:",
[HashPurpose.Attestation] = "gost3411:",
[HashPurpose.Interop] = "sha256:",
[HashPurpose.Secret] = "argon2id:",
},
HmacPurposeAlgorithms = new Dictionary<string, string>
{
[HmacPurpose.Signing] = HmacAlgorithms.HmacGost3411,
[HmacPurpose.Authentication] = HmacAlgorithms.HmacGost3411,
[HmacPurpose.WebhookInterop] = HmacAlgorithms.HmacSha256, // External compatibility
},
AllowInteropOverride = true,
};
/// <summary>
/// GB/T SM3 (Chinese) compliance profile.
/// Uses SM3 hash for all purposes except Interop (which remains SHA-256 for external compatibility).
/// </summary>
public static readonly ComplianceProfile Sm = new()
{
ProfileId = "sm",
StandardName = "GB/T (SM3)",
Description = "Chinese GB/T 32905-2016 SM3 cryptographic hash standard. Interop uses SHA-256 for external tool compatibility.",
PurposeAlgorithms = new Dictionary<string, string>
{
[HashPurpose.Graph] = HashAlgorithms.Sm3,
[HashPurpose.Symbol] = HashAlgorithms.Sm3,
[HashPurpose.Content] = HashAlgorithms.Sm3,
[HashPurpose.Merkle] = HashAlgorithms.Sm3,
[HashPurpose.Attestation] = HashAlgorithms.Sm3,
[HashPurpose.Interop] = HashAlgorithms.Sha256, // Override for external compatibility
[HashPurpose.Secret] = PasswordHashAlgorithms.Argon2id,
},
HashPrefixes = new Dictionary<string, string>
{
[HashPurpose.Graph] = "sm3:",
[HashPurpose.Symbol] = "sm3:",
[HashPurpose.Content] = "sm3:",
[HashPurpose.Merkle] = "sm3:",
[HashPurpose.Attestation] = "sm3:",
[HashPurpose.Interop] = "sha256:",
[HashPurpose.Secret] = "argon2id:",
},
HmacPurposeAlgorithms = new Dictionary<string, string>
{
[HmacPurpose.Signing] = HmacAlgorithms.HmacSm3,
[HmacPurpose.Authentication] = HmacAlgorithms.HmacSm3,
[HmacPurpose.WebhookInterop] = HmacAlgorithms.HmacSha256, // External compatibility
},
AllowInteropOverride = true,
};
/// <summary>
/// KCMVP (Korea Cryptographic Module Validation Program) compliance profile.
/// Uses SHA-256 for hashing. Note: ARIA/SEED/LEA are for encryption, KCDSA for signatures.
/// </summary>
public static readonly ComplianceProfile Kcmvp = new()
{
ProfileId = "kcmvp",
StandardName = "KCMVP (Korea)",
Description = "Korea Cryptographic Module Validation Program. Uses SHA-256 for hashing.",
PurposeAlgorithms = new Dictionary<string, string>
{
[HashPurpose.Graph] = HashAlgorithms.Sha256,
[HashPurpose.Symbol] = HashAlgorithms.Sha256,
[HashPurpose.Content] = HashAlgorithms.Sha256,
[HashPurpose.Merkle] = HashAlgorithms.Sha256,
[HashPurpose.Attestation] = HashAlgorithms.Sha256,
[HashPurpose.Interop] = HashAlgorithms.Sha256,
[HashPurpose.Secret] = PasswordHashAlgorithms.Argon2id,
},
HashPrefixes = new Dictionary<string, string>
{
[HashPurpose.Graph] = "sha256:",
[HashPurpose.Symbol] = "sha256:",
[HashPurpose.Content] = "sha256:",
[HashPurpose.Merkle] = "sha256:",
[HashPurpose.Attestation] = "sha256:",
[HashPurpose.Interop] = "sha256:",
[HashPurpose.Secret] = "argon2id:",
},
HmacPurposeAlgorithms = new Dictionary<string, string>
{
[HmacPurpose.Signing] = HmacAlgorithms.HmacSha256,
[HmacPurpose.Authentication] = HmacAlgorithms.HmacSha256,
[HmacPurpose.WebhookInterop] = HmacAlgorithms.HmacSha256,
},
AllowInteropOverride = true,
};
/// <summary>
/// eIDAS/ETSI TS 119 312 (European) compliance profile.
/// Uses SHA-256 for hashing per ETSI cryptographic suites specification.
/// </summary>
public static readonly ComplianceProfile Eidas = new()
{
ProfileId = "eidas",
StandardName = "eIDAS/ETSI TS 119 312",
Description = "European eIDAS regulation with ETSI TS 119 312 cryptographic suites. Uses SHA-256/384 for hashing.",
PurposeAlgorithms = new Dictionary<string, string>
{
[HashPurpose.Graph] = HashAlgorithms.Sha256,
[HashPurpose.Symbol] = HashAlgorithms.Sha256,
[HashPurpose.Content] = HashAlgorithms.Sha256,
[HashPurpose.Merkle] = HashAlgorithms.Sha256,
[HashPurpose.Attestation] = HashAlgorithms.Sha256,
[HashPurpose.Interop] = HashAlgorithms.Sha256,
[HashPurpose.Secret] = PasswordHashAlgorithms.Argon2id,
},
HashPrefixes = new Dictionary<string, string>
{
[HashPurpose.Graph] = "sha256:",
[HashPurpose.Symbol] = "sha256:",
[HashPurpose.Content] = "sha256:",
[HashPurpose.Merkle] = "sha256:",
[HashPurpose.Attestation] = "sha256:",
[HashPurpose.Interop] = "sha256:",
[HashPurpose.Secret] = "argon2id:",
},
HmacPurposeAlgorithms = new Dictionary<string, string>
{
[HmacPurpose.Signing] = HmacAlgorithms.HmacSha256,
[HmacPurpose.Authentication] = HmacAlgorithms.HmacSha256,
[HmacPurpose.WebhookInterop] = HmacAlgorithms.HmacSha256,
},
AllowInteropOverride = true,
};
/// <summary>
/// All built-in profiles indexed by profile ID.
/// </summary>
public static readonly IReadOnlyDictionary<string, ComplianceProfile> All =
new Dictionary<string, ComplianceProfile>(StringComparer.OrdinalIgnoreCase)
{
[World.ProfileId] = World,
[Fips.ProfileId] = Fips,
[Gost.ProfileId] = Gost,
[Sm.ProfileId] = Sm,
[Kcmvp.ProfileId] = Kcmvp,
[Eidas.ProfileId] = Eidas,
};
/// <summary>
/// Gets a profile by ID, returning the World profile if not found.
/// </summary>
/// <param name="profileId">The profile ID to look up.</param>
/// <returns>The matching profile, or World if not found.</returns>
public static ComplianceProfile GetProfile(string? profileId)
{
if (string.IsNullOrWhiteSpace(profileId))
{
return World;
}
return All.TryGetValue(profileId, out var profile) ? profile : World;
}
/// <summary>
/// Gets a profile by ID, throwing if not found.
/// </summary>
/// <param name="profileId">The profile ID to look up.</param>
/// <returns>The matching profile.</returns>
/// <exception cref="ArgumentException">Thrown when the profile ID is not found.</exception>
public static ComplianceProfile GetProfileOrThrow(string profileId)
{
if (string.IsNullOrWhiteSpace(profileId))
{
throw new ArgumentException("Profile ID cannot be null or empty.", nameof(profileId));
}
if (!All.TryGetValue(profileId, out var profile))
{
throw new ArgumentException(
$"Unknown compliance profile '{profileId}'. Valid profiles: {string.Join(", ", All.Keys)}",
nameof(profileId));
}
return profile;
}
}