Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.
This commit is contained in:
200
src/Policy/StellaOps.Policy.Engine/Crypto/CryptoRiskAtoms.cs
Normal file
200
src/Policy/StellaOps.Policy.Engine/Crypto/CryptoRiskAtoms.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Crypto;
|
||||
|
||||
/// <summary>
|
||||
/// Policy atoms for cryptographic risk evaluation.
|
||||
/// These atoms can be used in policy rules to gate or warn on crypto-related issues.
|
||||
/// </summary>
|
||||
public static class CryptoRiskAtoms
|
||||
{
|
||||
#region Atom Names
|
||||
|
||||
/// <summary>
|
||||
/// Atom for deprecated cryptographic algorithms (MD5, SHA-1, DES, etc.).
|
||||
/// </summary>
|
||||
public const string WeakCrypto = "WEAK_CRYPTO";
|
||||
|
||||
/// <summary>
|
||||
/// Atom for algorithms vulnerable to quantum computing attacks.
|
||||
/// </summary>
|
||||
public const string QuantumVulnerable = "QUANTUM_VULNERABLE";
|
||||
|
||||
/// <summary>
|
||||
/// Atom for deprecated algorithms that are cryptographically broken.
|
||||
/// </summary>
|
||||
public const string DeprecatedCrypto = "DEPRECATED_CRYPTO";
|
||||
|
||||
/// <summary>
|
||||
/// Atom for algorithms with insufficient key sizes.
|
||||
/// </summary>
|
||||
public const string InsufficientKeySize = "INSUFFICIENT_KEY_SIZE";
|
||||
|
||||
/// <summary>
|
||||
/// Atom for post-quantum ready algorithms (positive indicator).
|
||||
/// </summary>
|
||||
public const string PostQuantumReady = "POST_QUANTUM_READY";
|
||||
|
||||
/// <summary>
|
||||
/// Atom for algorithms that are FIPS-140 compliant.
|
||||
/// </summary>
|
||||
public const string FipsCompliant = "FIPS_COMPLIANT";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Algorithm Classifications
|
||||
|
||||
/// <summary>
|
||||
/// Deprecated/broken algorithms that should never be used for security.
|
||||
/// </summary>
|
||||
public static readonly ImmutableHashSet<string> DeprecatedAlgorithms = ImmutableHashSet.Create(
|
||||
StringComparer.OrdinalIgnoreCase,
|
||||
"MD2", "MD4", "MD5",
|
||||
"SHA1", "SHA-1",
|
||||
"DES", "3DES", "TRIPLE-DES", "TRIPLEDES",
|
||||
"RC2", "RC4",
|
||||
"BLOWFISH",
|
||||
"IDEA");
|
||||
|
||||
/// <summary>
|
||||
/// Algorithms considered weak but not yet deprecated.
|
||||
/// </summary>
|
||||
public static readonly ImmutableHashSet<string> WeakAlgorithms = ImmutableHashSet.Create(
|
||||
StringComparer.OrdinalIgnoreCase,
|
||||
"SHA-224",
|
||||
"AES-128-ECB", "AES-192-ECB", "AES-256-ECB");
|
||||
|
||||
/// <summary>
|
||||
/// Algorithms vulnerable to quantum computing attacks (Shor's algorithm).
|
||||
/// </summary>
|
||||
public static readonly ImmutableHashSet<string> QuantumVulnerableAlgorithms = ImmutableHashSet.Create(
|
||||
StringComparer.OrdinalIgnoreCase,
|
||||
"RSA", "RSA-1024", "RSA-2048", "RSA-3072", "RSA-4096",
|
||||
"DSA", "DSA-1024", "DSA-2048", "DSA-3072",
|
||||
"ECDSA", "ECDSA-P256", "ECDSA-P384", "ECDSA-P521",
|
||||
"ECDH", "ECDHE", "ECDH-P256", "ECDH-P384",
|
||||
"DH", "DHE", "DH-2048", "DH-3072",
|
||||
"ED25519", "ED448",
|
||||
"X25519", "X448");
|
||||
|
||||
/// <summary>
|
||||
/// Post-quantum cryptography algorithms (NIST standards and candidates).
|
||||
/// </summary>
|
||||
public static readonly ImmutableHashSet<string> PostQuantumAlgorithms = ImmutableHashSet.Create(
|
||||
StringComparer.OrdinalIgnoreCase,
|
||||
// NIST PQC Standards
|
||||
"ML-KEM", "ML-KEM-512", "ML-KEM-768", "ML-KEM-1024",
|
||||
"ML-DSA", "ML-DSA-44", "ML-DSA-65", "ML-DSA-87",
|
||||
"SLH-DSA", "SLH-DSA-128s", "SLH-DSA-128f", "SLH-DSA-192s", "SLH-DSA-192f", "SLH-DSA-256s", "SLH-DSA-256f",
|
||||
// Legacy names
|
||||
"KYBER", "KYBER-512", "KYBER-768", "KYBER-1024",
|
||||
"DILITHIUM", "DILITHIUM-2", "DILITHIUM-3", "DILITHIUM-5",
|
||||
"FALCON", "FALCON-512", "FALCON-1024",
|
||||
"SPHINCS+", "SPHINCS+-128s", "SPHINCS+-128f", "SPHINCS+-192s", "SPHINCS+-192f", "SPHINCS+-256s", "SPHINCS+-256f");
|
||||
|
||||
/// <summary>
|
||||
/// FIPS 140-2/140-3 approved algorithms.
|
||||
/// </summary>
|
||||
public static readonly ImmutableHashSet<string> FipsApprovedAlgorithms = ImmutableHashSet.Create(
|
||||
StringComparer.OrdinalIgnoreCase,
|
||||
// Hash functions
|
||||
"SHA-224", "SHA-256", "SHA-384", "SHA-512", "SHA-512/224", "SHA-512/256",
|
||||
"SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512",
|
||||
"SHAKE128", "SHAKE256",
|
||||
// Symmetric encryption
|
||||
"AES-128", "AES-192", "AES-256",
|
||||
"AES-128-CBC", "AES-192-CBC", "AES-256-CBC",
|
||||
"AES-128-GCM", "AES-192-GCM", "AES-256-GCM",
|
||||
"AES-128-CCM", "AES-192-CCM", "AES-256-CCM",
|
||||
"AES-128-CTR", "AES-192-CTR", "AES-256-CTR",
|
||||
// Asymmetric
|
||||
"RSA-2048", "RSA-3072", "RSA-4096",
|
||||
"ECDSA-P256", "ECDSA-P384", "ECDSA-P521",
|
||||
"ECDH-P256", "ECDH-P384", "ECDH-P521",
|
||||
// MACs
|
||||
"HMAC-SHA-256", "HMAC-SHA-384", "HMAC-SHA-512",
|
||||
"CMAC-AES-128", "CMAC-AES-192", "CMAC-AES-256");
|
||||
|
||||
#endregion
|
||||
|
||||
#region Minimum Key Sizes
|
||||
|
||||
/// <summary>
|
||||
/// Minimum acceptable key sizes by algorithm type.
|
||||
/// </summary>
|
||||
public static readonly ImmutableDictionary<string, int> MinimumKeySizes = ImmutableDictionary.CreateRange(
|
||||
StringComparer.OrdinalIgnoreCase,
|
||||
new Dictionary<string, int>
|
||||
{
|
||||
["RSA"] = 2048,
|
||||
["DSA"] = 2048,
|
||||
["DH"] = 2048,
|
||||
["DHE"] = 2048,
|
||||
["ECDSA"] = 256,
|
||||
["ECDH"] = 256,
|
||||
["ECDHE"] = 256,
|
||||
["ED25519"] = 256,
|
||||
["AES"] = 128,
|
||||
["CHACHA20"] = 256,
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Recommended key sizes for future-proofing.
|
||||
/// </summary>
|
||||
public static readonly ImmutableDictionary<string, int> RecommendedKeySizes = ImmutableDictionary.CreateRange(
|
||||
StringComparer.OrdinalIgnoreCase,
|
||||
new Dictionary<string, int>
|
||||
{
|
||||
["RSA"] = 3072,
|
||||
["DSA"] = 3072,
|
||||
["DH"] = 3072,
|
||||
["DHE"] = 3072,
|
||||
["ECDSA"] = 384,
|
||||
["ECDH"] = 384,
|
||||
["ECDHE"] = 384,
|
||||
["AES"] = 256,
|
||||
});
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result of evaluating a crypto risk atom.
|
||||
/// </summary>
|
||||
public sealed record CryptoAtomResult
|
||||
{
|
||||
/// <summary>Atom name that was evaluated.</summary>
|
||||
public required string AtomName { get; init; }
|
||||
|
||||
/// <summary>Whether the atom condition is triggered.</summary>
|
||||
public required bool Triggered { get; init; }
|
||||
|
||||
/// <summary>Severity level when triggered.</summary>
|
||||
public required CryptoSeverity Severity { get; init; }
|
||||
|
||||
/// <summary>Human-readable explanation.</summary>
|
||||
public required string Reason { get; init; }
|
||||
|
||||
/// <summary>Algorithms that caused this atom to trigger.</summary>
|
||||
public ImmutableArray<string> TriggeringAlgorithms { get; init; } = ImmutableArray<string>.Empty;
|
||||
|
||||
/// <summary>Recommendation for remediation.</summary>
|
||||
public string? Recommendation { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Severity levels for crypto findings.
|
||||
/// </summary>
|
||||
public enum CryptoSeverity
|
||||
{
|
||||
/// <summary>Informational only.</summary>
|
||||
Info,
|
||||
/// <summary>Low severity - should be addressed eventually.</summary>
|
||||
Low,
|
||||
/// <summary>Medium severity - should be addressed in near term.</summary>
|
||||
Medium,
|
||||
/// <summary>High severity - should be addressed promptly.</summary>
|
||||
High,
|
||||
/// <summary>Critical severity - immediate action required.</summary>
|
||||
Critical
|
||||
}
|
||||
319
src/Policy/StellaOps.Policy.Engine/Crypto/CryptoRiskEvaluator.cs
Normal file
319
src/Policy/StellaOps.Policy.Engine/Crypto/CryptoRiskEvaluator.cs
Normal file
@@ -0,0 +1,319 @@
|
||||
using System.Collections.Immutable;
|
||||
using StellaOps.Policy.Crypto;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Crypto;
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates cryptographic risk based on CBOM analysis results.
|
||||
/// Produces policy findings for crypto-related issues.
|
||||
/// </summary>
|
||||
public sealed class CryptoRiskEvaluator
|
||||
{
|
||||
private readonly CryptoRiskOptions _options;
|
||||
|
||||
public CryptoRiskEvaluator(CryptoRiskOptions? options = null)
|
||||
{
|
||||
_options = options ?? CryptoRiskOptions.Default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates all crypto risk atoms for a set of crypto assets.
|
||||
/// </summary>
|
||||
public ImmutableArray<CryptoAtomResult> Evaluate(ImmutableArray<CryptoAsset> assets)
|
||||
{
|
||||
var results = new List<CryptoAtomResult>();
|
||||
|
||||
// Evaluate each atom type
|
||||
results.Add(EvaluateDeprecatedCrypto(assets));
|
||||
results.Add(EvaluateWeakCrypto(assets));
|
||||
results.Add(EvaluateQuantumVulnerable(assets));
|
||||
results.Add(EvaluateInsufficientKeySize(assets));
|
||||
results.Add(EvaluatePostQuantumReady(assets));
|
||||
results.Add(EvaluateFipsCompliance(assets));
|
||||
|
||||
return results.ToImmutableArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the DEPRECATED_CRYPTO atom.
|
||||
/// Triggered when cryptographically broken algorithms are detected.
|
||||
/// </summary>
|
||||
public CryptoAtomResult EvaluateDeprecatedCrypto(ImmutableArray<CryptoAsset> assets)
|
||||
{
|
||||
var deprecated = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
if (string.IsNullOrEmpty(asset.AlgorithmName))
|
||||
continue;
|
||||
|
||||
var algUpper = asset.AlgorithmName.ToUpperInvariant();
|
||||
|
||||
if (CryptoRiskAtoms.DeprecatedAlgorithms.Contains(asset.AlgorithmName) ||
|
||||
CryptoRiskAtoms.DeprecatedAlgorithms.Any(d => algUpper.Contains(d)))
|
||||
{
|
||||
deprecated.Add(asset.AlgorithmName);
|
||||
}
|
||||
}
|
||||
|
||||
return new CryptoAtomResult
|
||||
{
|
||||
AtomName = CryptoRiskAtoms.DeprecatedCrypto,
|
||||
Triggered = deprecated.Count > 0,
|
||||
Severity = deprecated.Count > 0 ? CryptoSeverity.Critical : CryptoSeverity.Info,
|
||||
Reason = deprecated.Count > 0
|
||||
? $"Found {deprecated.Count} deprecated cryptographic algorithm(s): {string.Join(", ", deprecated.OrderBy(x => x))}"
|
||||
: "No deprecated algorithms detected",
|
||||
TriggeringAlgorithms = deprecated.OrderBy(x => x).ToImmutableArray(),
|
||||
Recommendation = deprecated.Count > 0
|
||||
? "Replace deprecated algorithms with modern alternatives: MD5/SHA-1 → SHA-256+, DES/3DES → AES-256-GCM"
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the WEAK_CRYPTO atom.
|
||||
/// Triggered when algorithms are weak but not yet deprecated.
|
||||
/// </summary>
|
||||
public CryptoAtomResult EvaluateWeakCrypto(ImmutableArray<CryptoAsset> assets)
|
||||
{
|
||||
var weak = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
if (string.IsNullOrEmpty(asset.AlgorithmName))
|
||||
continue;
|
||||
|
||||
var algUpper = asset.AlgorithmName.ToUpperInvariant();
|
||||
|
||||
// Check explicit weak algorithms
|
||||
if (CryptoRiskAtoms.WeakAlgorithms.Contains(asset.AlgorithmName) ||
|
||||
CryptoRiskAtoms.WeakAlgorithms.Any(w => algUpper.Contains(w)))
|
||||
{
|
||||
weak.Add(asset.AlgorithmName);
|
||||
}
|
||||
|
||||
// Check ECB mode (weak for block ciphers)
|
||||
if (algUpper.Contains("ECB"))
|
||||
{
|
||||
weak.Add(asset.AlgorithmName);
|
||||
}
|
||||
}
|
||||
|
||||
return new CryptoAtomResult
|
||||
{
|
||||
AtomName = CryptoRiskAtoms.WeakCrypto,
|
||||
Triggered = weak.Count > 0,
|
||||
Severity = weak.Count > 0 ? CryptoSeverity.High : CryptoSeverity.Info,
|
||||
Reason = weak.Count > 0
|
||||
? $"Found {weak.Count} weak cryptographic algorithm(s): {string.Join(", ", weak.OrderBy(x => x))}"
|
||||
: "No weak algorithms detected",
|
||||
TriggeringAlgorithms = weak.OrderBy(x => x).ToImmutableArray(),
|
||||
Recommendation = weak.Count > 0
|
||||
? "Replace weak algorithms with stronger variants: ECB → GCM/CBC, SHA-224 → SHA-256+"
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the QUANTUM_VULNERABLE atom.
|
||||
/// Triggered when algorithms are vulnerable to quantum computing attacks.
|
||||
/// </summary>
|
||||
public CryptoAtomResult EvaluateQuantumVulnerable(ImmutableArray<CryptoAsset> assets)
|
||||
{
|
||||
var vulnerable = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
if (string.IsNullOrEmpty(asset.AlgorithmName))
|
||||
continue;
|
||||
|
||||
// Check if algorithm is quantum-vulnerable
|
||||
if (CryptoRiskAtoms.QuantumVulnerableAlgorithms.Contains(asset.AlgorithmName) ||
|
||||
CryptoRiskAtoms.QuantumVulnerableAlgorithms.Any(q => asset.AlgorithmName.StartsWith(q, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
vulnerable.Add(asset.AlgorithmName);
|
||||
}
|
||||
|
||||
// RSA, DSA, ECDSA, ECDH, DH are all vulnerable
|
||||
var algUpper = asset.AlgorithmName.ToUpperInvariant();
|
||||
if (algUpper.StartsWith("RSA") || algUpper.StartsWith("DSA") ||
|
||||
algUpper.StartsWith("ECDSA") || algUpper.StartsWith("ECDH") ||
|
||||
algUpper.StartsWith("DH") || algUpper.StartsWith("DHE"))
|
||||
{
|
||||
vulnerable.Add(asset.AlgorithmName);
|
||||
}
|
||||
}
|
||||
|
||||
// Determine severity based on options
|
||||
var severity = _options.TreatQuantumVulnerableAs;
|
||||
if (!_options.EnableQuantumRiskWarnings)
|
||||
{
|
||||
severity = CryptoSeverity.Info;
|
||||
}
|
||||
|
||||
return new CryptoAtomResult
|
||||
{
|
||||
AtomName = CryptoRiskAtoms.QuantumVulnerable,
|
||||
Triggered = vulnerable.Count > 0 && _options.EnableQuantumRiskWarnings,
|
||||
Severity = vulnerable.Count > 0 ? severity : CryptoSeverity.Info,
|
||||
Reason = vulnerable.Count > 0
|
||||
? $"Found {vulnerable.Count} quantum-vulnerable algorithm(s): {string.Join(", ", vulnerable.OrderBy(x => x))}"
|
||||
: "No quantum-vulnerable algorithms detected",
|
||||
TriggeringAlgorithms = vulnerable.OrderBy(x => x).ToImmutableArray(),
|
||||
Recommendation = vulnerable.Count > 0
|
||||
? "Plan migration to post-quantum cryptography: RSA/ECDSA → ML-DSA, ECDH → ML-KEM"
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the INSUFFICIENT_KEY_SIZE atom.
|
||||
/// Triggered when key sizes are below minimum thresholds.
|
||||
/// </summary>
|
||||
public CryptoAtomResult EvaluateInsufficientKeySize(ImmutableArray<CryptoAsset> assets)
|
||||
{
|
||||
var insufficient = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
if (string.IsNullOrEmpty(asset.AlgorithmName) || !asset.KeySizeBits.HasValue)
|
||||
continue;
|
||||
|
||||
var keySize = asset.KeySizeBits.Value;
|
||||
|
||||
// Check minimum key size for algorithm type
|
||||
foreach (var (algType, minSize) in CryptoRiskAtoms.MinimumKeySizes)
|
||||
{
|
||||
if (asset.AlgorithmName.StartsWith(algType, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (keySize < minSize)
|
||||
{
|
||||
insufficient.Add($"{asset.AlgorithmName}-{keySize}");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new CryptoAtomResult
|
||||
{
|
||||
AtomName = CryptoRiskAtoms.InsufficientKeySize,
|
||||
Triggered = insufficient.Count > 0,
|
||||
Severity = insufficient.Count > 0 ? CryptoSeverity.High : CryptoSeverity.Info,
|
||||
Reason = insufficient.Count > 0
|
||||
? $"Found {insufficient.Count} algorithm(s) with insufficient key size: {string.Join(", ", insufficient.OrderBy(x => x))}"
|
||||
: "All algorithms have sufficient key sizes",
|
||||
TriggeringAlgorithms = insufficient.OrderBy(x => x).ToImmutableArray(),
|
||||
Recommendation = insufficient.Count > 0
|
||||
? "Increase key sizes: RSA ≥2048, ECDSA ≥256, AES ≥128"
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the POST_QUANTUM_READY atom.
|
||||
/// This is a positive indicator - triggered when PQ algorithms are present.
|
||||
/// </summary>
|
||||
public CryptoAtomResult EvaluatePostQuantumReady(ImmutableArray<CryptoAsset> assets)
|
||||
{
|
||||
var pqReady = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
if (string.IsNullOrEmpty(asset.AlgorithmName))
|
||||
continue;
|
||||
|
||||
if (CryptoRiskAtoms.PostQuantumAlgorithms.Contains(asset.AlgorithmName) ||
|
||||
CryptoRiskAtoms.PostQuantumAlgorithms.Any(pq => asset.AlgorithmName.StartsWith(pq, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
pqReady.Add(asset.AlgorithmName);
|
||||
}
|
||||
}
|
||||
|
||||
return new CryptoAtomResult
|
||||
{
|
||||
AtomName = CryptoRiskAtoms.PostQuantumReady,
|
||||
Triggered = pqReady.Count > 0,
|
||||
Severity = CryptoSeverity.Info, // Positive indicator
|
||||
Reason = pqReady.Count > 0
|
||||
? $"Found {pqReady.Count} post-quantum algorithm(s): {string.Join(", ", pqReady.OrderBy(x => x))}"
|
||||
: "No post-quantum algorithms detected",
|
||||
TriggeringAlgorithms = pqReady.OrderBy(x => x).ToImmutableArray(),
|
||||
Recommendation = pqReady.Count == 0
|
||||
? "Consider adopting ML-KEM/ML-DSA for quantum-resistant cryptography"
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the FIPS_COMPLIANT atom.
|
||||
/// Checks if all algorithms are FIPS 140-2/140-3 approved.
|
||||
/// </summary>
|
||||
public CryptoAtomResult EvaluateFipsCompliance(ImmutableArray<CryptoAsset> assets)
|
||||
{
|
||||
var nonFips = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
int fipsCount = 0;
|
||||
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
if (string.IsNullOrEmpty(asset.AlgorithmName))
|
||||
continue;
|
||||
|
||||
if (CryptoRiskAtoms.FipsApprovedAlgorithms.Contains(asset.AlgorithmName) ||
|
||||
CryptoRiskAtoms.FipsApprovedAlgorithms.Any(f => asset.AlgorithmName.StartsWith(f, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
fipsCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
nonFips.Add(asset.AlgorithmName);
|
||||
}
|
||||
}
|
||||
|
||||
var isCompliant = nonFips.Count == 0 && fipsCount > 0;
|
||||
|
||||
return new CryptoAtomResult
|
||||
{
|
||||
AtomName = CryptoRiskAtoms.FipsCompliant,
|
||||
Triggered = !isCompliant && _options.RequireFipsCompliance,
|
||||
Severity = !isCompliant && _options.RequireFipsCompliance ? CryptoSeverity.High : CryptoSeverity.Info,
|
||||
Reason = isCompliant
|
||||
? $"All {fipsCount} algorithm(s) are FIPS compliant"
|
||||
: nonFips.Count > 0
|
||||
? $"Found {nonFips.Count} non-FIPS algorithm(s): {string.Join(", ", nonFips.OrderBy(x => x))}"
|
||||
: "No cryptographic algorithms detected",
|
||||
TriggeringAlgorithms = nonFips.OrderBy(x => x).ToImmutableArray(),
|
||||
Recommendation = !isCompliant && _options.RequireFipsCompliance
|
||||
? "Replace non-FIPS algorithms with FIPS 140-2/140-3 approved alternatives"
|
||||
: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options for crypto risk evaluation.
|
||||
/// </summary>
|
||||
public sealed record CryptoRiskOptions
|
||||
{
|
||||
/// <summary>Default options.</summary>
|
||||
public static readonly CryptoRiskOptions Default = new();
|
||||
|
||||
/// <summary>Whether to enable quantum vulnerability warnings.</summary>
|
||||
public bool EnableQuantumRiskWarnings { get; init; } = true;
|
||||
|
||||
/// <summary>Severity level for quantum-vulnerable algorithms.</summary>
|
||||
public CryptoSeverity TreatQuantumVulnerableAs { get; init; } = CryptoSeverity.Medium;
|
||||
|
||||
/// <summary>Whether FIPS compliance is required.</summary>
|
||||
public bool RequireFipsCompliance { get; init; } = false;
|
||||
|
||||
/// <summary>Whether to block on deprecated algorithms.</summary>
|
||||
public bool BlockOnDeprecated { get; init; } = true;
|
||||
|
||||
/// <summary>Whether to block on weak algorithms.</summary>
|
||||
public bool BlockOnWeak { get; init; } = false;
|
||||
|
||||
/// <summary>Whether to block on insufficient key sizes.</summary>
|
||||
public bool BlockOnInsufficientKeySize { get; init; } = true;
|
||||
}
|
||||
Reference in New Issue
Block a user