Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.
This commit is contained in:
@@ -0,0 +1,488 @@
|
||||
using System.Collections.Immutable;
|
||||
using StellaOps.Scanner.Core.Contracts;
|
||||
using StellaOps.Scanner.Emit.Cbom;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Java.Internal.Crypto;
|
||||
|
||||
/// <summary>
|
||||
/// Extracts cryptographic assets from Java/Kotlin libraries and packages.
|
||||
/// Analyzes java.security, javax.crypto, and BouncyCastle usage patterns.
|
||||
/// </summary>
|
||||
public sealed class JavaCryptoExtractor : ICryptoAssetExtractor
|
||||
{
|
||||
private static readonly ImmutableArray<string> Ecosystems = ImmutableArray.Create("maven", "gradle");
|
||||
|
||||
public ImmutableArray<string> SupportedEcosystems => Ecosystems;
|
||||
|
||||
/// <summary>
|
||||
/// Known crypto-related Maven/Gradle packages.
|
||||
/// </summary>
|
||||
private static readonly ImmutableHashSet<string> CryptoPackages = ImmutableHashSet.Create(
|
||||
StringComparer.OrdinalIgnoreCase,
|
||||
// BouncyCastle
|
||||
"org.bouncycastle:bcprov-jdk18on",
|
||||
"org.bouncycastle:bcprov-jdk15on",
|
||||
"org.bouncycastle:bcpkix-jdk18on",
|
||||
"org.bouncycastle:bcpkix-jdk15on",
|
||||
"org.bouncycastle:bcpg-jdk18on",
|
||||
"org.bouncycastle:bctls-jdk18on",
|
||||
"org.bouncycastle:bcutil-jdk18on",
|
||||
// JCA/JCE providers
|
||||
"org.conscrypt:conscrypt-openjdk-uber",
|
||||
"com.amazon.corretto:amazon-corretto-crypto-provider",
|
||||
// JWT libraries
|
||||
"io.jsonwebtoken:jjwt-api",
|
||||
"io.jsonwebtoken:jjwt-impl",
|
||||
"com.auth0:java-jwt",
|
||||
"com.nimbusds:nimbus-jose-jwt",
|
||||
"org.bitbucket.b_c:jose4j",
|
||||
// Password hashing
|
||||
"org.mindrot:jbcrypt",
|
||||
"de.mkammerer:argon2-jvm",
|
||||
"com.lambdaworks:scrypt",
|
||||
"at.favre.lib:bcrypt",
|
||||
// TLS/SSL
|
||||
"io.netty:netty-handler",
|
||||
"org.eclipse.jetty:jetty-alpn-java-client",
|
||||
// Crypto utilities
|
||||
"commons-codec:commons-codec",
|
||||
"com.google.crypto.tink:tink",
|
||||
"org.apache.shiro:shiro-crypto-core",
|
||||
"org.jasypt:jasypt",
|
||||
"org.apache.commons:commons-crypto",
|
||||
// Key management
|
||||
"com.google.cloud:google-cloud-kms",
|
||||
"software.amazon.awssdk:kms",
|
||||
"com.azure:azure-security-keyvault-keys"
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Crypto provider patterns in Java.
|
||||
/// </summary>
|
||||
private static readonly ImmutableArray<string> CryptoProviderIndicators = ImmutableArray.Create(
|
||||
"java.security",
|
||||
"javax.crypto",
|
||||
"org.bouncycastle",
|
||||
"Security.addProvider",
|
||||
"KeyStore",
|
||||
"Cipher",
|
||||
"MessageDigest",
|
||||
"Signature",
|
||||
"Mac",
|
||||
"KeyGenerator",
|
||||
"KeyPairGenerator",
|
||||
"SecretKeyFactory",
|
||||
"KeyAgreement"
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Algorithm patterns to detect in package names and identifiers.
|
||||
/// </summary>
|
||||
private static readonly ImmutableArray<CryptoAlgorithmPattern> AlgorithmPatterns = ImmutableArray.Create(
|
||||
// Hash algorithms
|
||||
new CryptoAlgorithmPattern("MD5", "1.2.840.113549.2.5", CryptoPrimitive.Hash, CryptoFunction.Digest, 128, IsDeprecated: true),
|
||||
new CryptoAlgorithmPattern("SHA-1", "1.3.14.3.2.26", CryptoPrimitive.Hash, CryptoFunction.Digest, 160, IsDeprecated: true),
|
||||
new CryptoAlgorithmPattern("SHA1", "1.3.14.3.2.26", CryptoPrimitive.Hash, CryptoFunction.Digest, 160, IsDeprecated: true),
|
||||
new CryptoAlgorithmPattern("SHA-256", "2.16.840.1.101.3.4.2.1", CryptoPrimitive.Hash, CryptoFunction.Digest, 256),
|
||||
new CryptoAlgorithmPattern("SHA256", "2.16.840.1.101.3.4.2.1", CryptoPrimitive.Hash, CryptoFunction.Digest, 256),
|
||||
new CryptoAlgorithmPattern("SHA-384", "2.16.840.1.101.3.4.2.2", CryptoPrimitive.Hash, CryptoFunction.Digest, 384),
|
||||
new CryptoAlgorithmPattern("SHA-512", "2.16.840.1.101.3.4.2.3", CryptoPrimitive.Hash, CryptoFunction.Digest, 512),
|
||||
new CryptoAlgorithmPattern("SHA-3", "2.16.840.1.101.3.4.2.8", CryptoPrimitive.Hash, CryptoFunction.Digest, 256),
|
||||
new CryptoAlgorithmPattern("SHA3-256", "2.16.840.1.101.3.4.2.8", CryptoPrimitive.Hash, CryptoFunction.Digest, 256),
|
||||
new CryptoAlgorithmPattern("SHA3-512", "2.16.840.1.101.3.4.2.10", CryptoPrimitive.Hash, CryptoFunction.Digest, 512),
|
||||
new CryptoAlgorithmPattern("BLAKE2", null, CryptoPrimitive.Hash, CryptoFunction.Digest, 256),
|
||||
new CryptoAlgorithmPattern("BLAKE3", null, CryptoPrimitive.Hash, CryptoFunction.Digest, 256),
|
||||
|
||||
// Symmetric ciphers
|
||||
new CryptoAlgorithmPattern("AES", "2.16.840.1.101.3.4.1", CryptoPrimitive.BlockCipher, CryptoFunction.Encrypt, 256),
|
||||
new CryptoAlgorithmPattern("AES/GCM", "2.16.840.1.101.3.4.1.46", CryptoPrimitive.Aead, CryptoFunction.Encrypt, 256),
|
||||
new CryptoAlgorithmPattern("AES/CBC", "2.16.840.1.101.3.4.1.2", CryptoPrimitive.BlockCipher, CryptoFunction.Encrypt, 256),
|
||||
new CryptoAlgorithmPattern("AES/CTR", "2.16.840.1.101.3.4.1.42", CryptoPrimitive.StreamCipher, CryptoFunction.Encrypt, 256),
|
||||
new CryptoAlgorithmPattern("DES", "1.3.14.3.2.7", CryptoPrimitive.BlockCipher, CryptoFunction.Encrypt, 56, IsDeprecated: true),
|
||||
new CryptoAlgorithmPattern("DESede", "1.2.840.113549.3.7", CryptoPrimitive.BlockCipher, CryptoFunction.Encrypt, 168, IsWeak: true),
|
||||
new CryptoAlgorithmPattern("3DES", "1.2.840.113549.3.7", CryptoPrimitive.BlockCipher, CryptoFunction.Encrypt, 168, IsWeak: true),
|
||||
new CryptoAlgorithmPattern("TripleDES", "1.2.840.113549.3.7", CryptoPrimitive.BlockCipher, CryptoFunction.Encrypt, 168, IsWeak: true),
|
||||
new CryptoAlgorithmPattern("Blowfish", null, CryptoPrimitive.BlockCipher, CryptoFunction.Encrypt, 128, IsWeak: true),
|
||||
new CryptoAlgorithmPattern("RC4", null, CryptoPrimitive.StreamCipher, CryptoFunction.Encrypt, 128, IsDeprecated: true),
|
||||
new CryptoAlgorithmPattern("RC2", null, CryptoPrimitive.BlockCipher, CryptoFunction.Encrypt, 128, IsDeprecated: true),
|
||||
new CryptoAlgorithmPattern("ChaCha20", null, CryptoPrimitive.StreamCipher, CryptoFunction.Encrypt, 256),
|
||||
new CryptoAlgorithmPattern("ChaCha20-Poly1305", null, CryptoPrimitive.Aead, CryptoFunction.Encrypt, 256),
|
||||
new CryptoAlgorithmPattern("XChaCha20", null, CryptoPrimitive.StreamCipher, CryptoFunction.Encrypt, 256),
|
||||
|
||||
// Asymmetric algorithms
|
||||
new CryptoAlgorithmPattern("RSA", "1.2.840.113549.1.1.1", CryptoPrimitive.Rsa, CryptoFunction.Sign, 2048, IsQuantumVulnerable: true),
|
||||
new CryptoAlgorithmPattern("DSA", "1.2.840.10040.4.1", CryptoPrimitive.Dlog, CryptoFunction.Sign, 2048, IsQuantumVulnerable: true),
|
||||
new CryptoAlgorithmPattern("EC", "1.2.840.10045.2.1", CryptoPrimitive.Ec, CryptoFunction.Sign, 256, IsQuantumVulnerable: true),
|
||||
new CryptoAlgorithmPattern("ECDSA", "1.2.840.10045.4.3", CryptoPrimitive.Ec, CryptoFunction.Sign, 256, IsQuantumVulnerable: true),
|
||||
new CryptoAlgorithmPattern("ECDH", "1.3.132.1.12", CryptoPrimitive.Ec, CryptoFunction.KeyAgree, 256, IsQuantumVulnerable: true),
|
||||
new CryptoAlgorithmPattern("Ed25519", "1.3.101.112", CryptoPrimitive.Ec, CryptoFunction.Sign, 256, IsQuantumVulnerable: true),
|
||||
new CryptoAlgorithmPattern("Ed448", "1.3.101.113", CryptoPrimitive.Ec, CryptoFunction.Sign, 448, IsQuantumVulnerable: true),
|
||||
new CryptoAlgorithmPattern("X25519", "1.3.101.110", CryptoPrimitive.Ec, CryptoFunction.KeyAgree, 256, IsQuantumVulnerable: true),
|
||||
new CryptoAlgorithmPattern("X448", "1.3.101.111", CryptoPrimitive.Ec, CryptoFunction.KeyAgree, 448, IsQuantumVulnerable: true),
|
||||
new CryptoAlgorithmPattern("DiffieHellman", null, CryptoPrimitive.Dlog, CryptoFunction.KeyAgree, 2048, IsQuantumVulnerable: true),
|
||||
|
||||
// Key derivation
|
||||
new CryptoAlgorithmPattern("PBKDF2", "1.2.840.113549.1.5.12", CryptoPrimitive.Pbkdf, CryptoFunction.Derive, 256),
|
||||
new CryptoAlgorithmPattern("HKDF", null, CryptoPrimitive.Kdf, CryptoFunction.Derive, 256),
|
||||
new CryptoAlgorithmPattern("BCrypt", null, CryptoPrimitive.Pbkdf, CryptoFunction.Derive, 184),
|
||||
new CryptoAlgorithmPattern("SCrypt", null, CryptoPrimitive.Pbkdf, CryptoFunction.Derive, 256),
|
||||
new CryptoAlgorithmPattern("Argon2", null, CryptoPrimitive.Pbkdf, CryptoFunction.Derive, 256),
|
||||
new CryptoAlgorithmPattern("Argon2id", null, CryptoPrimitive.Pbkdf, CryptoFunction.Derive, 256),
|
||||
|
||||
// MACs
|
||||
new CryptoAlgorithmPattern("HmacSHA256", "1.2.840.113549.2.9", CryptoPrimitive.Mac, CryptoFunction.Tag, 256),
|
||||
new CryptoAlgorithmPattern("HmacSHA384", "1.2.840.113549.2.10", CryptoPrimitive.Mac, CryptoFunction.Tag, 384),
|
||||
new CryptoAlgorithmPattern("HmacSHA512", "1.2.840.113549.2.11", CryptoPrimitive.Mac, CryptoFunction.Tag, 512),
|
||||
new CryptoAlgorithmPattern("HmacMD5", "1.3.6.1.5.5.8.1.1", CryptoPrimitive.Mac, CryptoFunction.Tag, 128, IsDeprecated: true),
|
||||
new CryptoAlgorithmPattern("HmacSHA1", "1.2.840.113549.2.7", CryptoPrimitive.Mac, CryptoFunction.Tag, 160, IsDeprecated: true),
|
||||
new CryptoAlgorithmPattern("Poly1305", null, CryptoPrimitive.Mac, CryptoFunction.Tag, 128),
|
||||
new CryptoAlgorithmPattern("GMAC", null, CryptoPrimitive.Mac, CryptoFunction.Tag, 128),
|
||||
|
||||
// Post-quantum (BouncyCastle implementations)
|
||||
new CryptoAlgorithmPattern("Kyber", null, CryptoPrimitive.Kem, CryptoFunction.Encapsulate, 256, IsPostQuantum: true),
|
||||
new CryptoAlgorithmPattern("ML-KEM", null, CryptoPrimitive.Kem, CryptoFunction.Encapsulate, 256, IsPostQuantum: true),
|
||||
new CryptoAlgorithmPattern("Dilithium", null, CryptoPrimitive.Lattice, CryptoFunction.Sign, 256, IsPostQuantum: true),
|
||||
new CryptoAlgorithmPattern("ML-DSA", null, CryptoPrimitive.Lattice, CryptoFunction.Sign, 256, IsPostQuantum: true),
|
||||
new CryptoAlgorithmPattern("SPHINCS+", null, CryptoPrimitive.Hash, CryptoFunction.Sign, 256, IsPostQuantum: true),
|
||||
new CryptoAlgorithmPattern("SLH-DSA", null, CryptoPrimitive.Hash, CryptoFunction.Sign, 256, IsPostQuantum: true),
|
||||
new CryptoAlgorithmPattern("NTRU", null, CryptoPrimitive.Lattice, CryptoFunction.Encapsulate, 256, IsPostQuantum: true),
|
||||
new CryptoAlgorithmPattern("FrodoKEM", null, CryptoPrimitive.Kem, CryptoFunction.Encapsulate, 256, IsPostQuantum: true)
|
||||
);
|
||||
|
||||
public Task<ImmutableArray<CryptoAsset>> ExtractAsync(
|
||||
AggregatedComponent component,
|
||||
CryptoAnalysisContext analysisContext,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var assets = new List<CryptoAsset>();
|
||||
|
||||
var packageName = component.Identity.Name ?? string.Empty;
|
||||
var purl = component.Identity.Purl ?? string.Empty;
|
||||
|
||||
// Skip if not a Java package
|
||||
if (!purl.StartsWith("pkg:maven/", StringComparison.OrdinalIgnoreCase) &&
|
||||
!purl.StartsWith("pkg:gradle/", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Task.FromResult(ImmutableArray<CryptoAsset>.Empty);
|
||||
}
|
||||
|
||||
// Check for known crypto packages by group:artifact format
|
||||
var groupArtifact = ExtractGroupArtifact(purl);
|
||||
if (CryptoPackages.Contains(groupArtifact))
|
||||
{
|
||||
var cryptoAssets = ExtractFromKnownPackage(component, groupArtifact);
|
||||
assets.AddRange(cryptoAssets);
|
||||
}
|
||||
|
||||
// Check package name for algorithm patterns
|
||||
foreach (var pattern in AlgorithmPatterns)
|
||||
{
|
||||
if (packageName.Contains(pattern.Name, StringComparison.OrdinalIgnoreCase) ||
|
||||
groupArtifact.Contains(pattern.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var asset = CreateAssetFromPattern(component, pattern);
|
||||
if (!assets.Any(a => a.AlgorithmName == asset.AlgorithmName))
|
||||
{
|
||||
assets.Add(asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check metadata for crypto provider evidence
|
||||
if (component.Metadata?.Properties != null)
|
||||
{
|
||||
foreach (var (key, value) in component.Metadata.Properties)
|
||||
{
|
||||
// Check for crypto provider indicators
|
||||
foreach (var indicator in CryptoProviderIndicators)
|
||||
{
|
||||
if (value.Contains(indicator, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Look for specific algorithms
|
||||
foreach (var pattern in AlgorithmPatterns)
|
||||
{
|
||||
if (value.Contains(pattern.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var asset = CreateAssetFromPattern(component, pattern, $"property:{key}");
|
||||
if (!assets.Any(a => a.AlgorithmName == asset.AlgorithmName))
|
||||
{
|
||||
assets.Add(asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(assets.ToImmutableArray());
|
||||
}
|
||||
|
||||
private static string ExtractGroupArtifact(string purl)
|
||||
{
|
||||
// Extract group:artifact from pkg:maven/group/artifact@version
|
||||
var prefix = purl.StartsWith("pkg:maven/", StringComparison.OrdinalIgnoreCase) ? "pkg:maven/" :
|
||||
purl.StartsWith("pkg:gradle/", StringComparison.OrdinalIgnoreCase) ? "pkg:gradle/" : null;
|
||||
|
||||
if (prefix == null) return string.Empty;
|
||||
|
||||
var rest = purl[prefix.Length..];
|
||||
var versionIdx = rest.IndexOf('@');
|
||||
if (versionIdx > 0)
|
||||
{
|
||||
rest = rest[..versionIdx];
|
||||
}
|
||||
|
||||
// Replace / with : for group:artifact format
|
||||
return rest.Replace('/', ':');
|
||||
}
|
||||
|
||||
private static IEnumerable<CryptoAsset> ExtractFromKnownPackage(AggregatedComponent component, string groupArtifact)
|
||||
{
|
||||
var assets = new List<CryptoAsset>();
|
||||
|
||||
if (groupArtifact.Contains("bouncycastle", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// BouncyCastle provides comprehensive crypto
|
||||
var bcAlgorithms = AlgorithmPatterns.Where(p =>
|
||||
p.Name == "AES" || p.Name == "RSA" || p.Name == "ECDSA" ||
|
||||
p.Name == "SHA-256" || p.Name == "SHA-512" || p.Name == "ChaCha20-Poly1305" ||
|
||||
p.Name == "Ed25519" || p.Name == "X25519" || p.IsPostQuantum);
|
||||
|
||||
foreach (var pattern in bcAlgorithms)
|
||||
{
|
||||
assets.Add(CreateAssetFromPattern(component, pattern, $"package:{groupArtifact}",
|
||||
implementationPlatform: "BouncyCastle"));
|
||||
}
|
||||
}
|
||||
else if (groupArtifact.Contains("jjwt", StringComparison.OrdinalIgnoreCase) ||
|
||||
groupArtifact.Contains("java-jwt", StringComparison.OrdinalIgnoreCase) ||
|
||||
groupArtifact.Contains("nimbus-jose-jwt", StringComparison.OrdinalIgnoreCase) ||
|
||||
groupArtifact.Contains("jose4j", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// JWT libraries use various algorithms
|
||||
var jwtAlgorithms = new[]
|
||||
{
|
||||
AlgorithmPatterns.First(p => p.Name == "RSA"),
|
||||
AlgorithmPatterns.First(p => p.Name == "ECDSA"),
|
||||
AlgorithmPatterns.First(p => p.Name == "HmacSHA256"),
|
||||
AlgorithmPatterns.First(p => p.Name == "HmacSHA512"),
|
||||
AlgorithmPatterns.First(p => p.Name == "Ed25519"),
|
||||
AlgorithmPatterns.First(p => p.Name == "AES/GCM")
|
||||
};
|
||||
|
||||
foreach (var pattern in jwtAlgorithms)
|
||||
{
|
||||
assets.Add(CreateAssetFromPattern(component, pattern, $"package:{groupArtifact}"));
|
||||
}
|
||||
}
|
||||
else if (groupArtifact.Contains("jbcrypt", StringComparison.OrdinalIgnoreCase) ||
|
||||
groupArtifact.Contains("bcrypt", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
assets.Add(CreateAssetFromPattern(component,
|
||||
AlgorithmPatterns.First(p => p.Name == "BCrypt"), $"package:{groupArtifact}"));
|
||||
}
|
||||
else if (groupArtifact.Contains("argon2", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
assets.Add(CreateAssetFromPattern(component,
|
||||
AlgorithmPatterns.First(p => p.Name == "Argon2id"), $"package:{groupArtifact}"));
|
||||
}
|
||||
else if (groupArtifact.Contains("scrypt", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
assets.Add(CreateAssetFromPattern(component,
|
||||
AlgorithmPatterns.First(p => p.Name == "SCrypt"), $"package:{groupArtifact}"));
|
||||
}
|
||||
else if (groupArtifact.Contains("tink", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Google Tink provides modern crypto
|
||||
var tinkAlgorithms = new[]
|
||||
{
|
||||
AlgorithmPatterns.First(p => p.Name == "AES/GCM"),
|
||||
AlgorithmPatterns.First(p => p.Name == "ChaCha20-Poly1305"),
|
||||
AlgorithmPatterns.First(p => p.Name == "ECDSA"),
|
||||
AlgorithmPatterns.First(p => p.Name == "Ed25519"),
|
||||
AlgorithmPatterns.First(p => p.Name == "HKDF")
|
||||
};
|
||||
|
||||
foreach (var pattern in tinkAlgorithms)
|
||||
{
|
||||
assets.Add(CreateAssetFromPattern(component, pattern, $"package:{groupArtifact}",
|
||||
implementationPlatform: "Google Tink"));
|
||||
}
|
||||
}
|
||||
else if (groupArtifact.Contains("conscrypt", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Conscrypt OpenSSL-based provider
|
||||
var conscryptAlgorithms = new[]
|
||||
{
|
||||
AlgorithmPatterns.First(p => p.Name == "AES/GCM"),
|
||||
AlgorithmPatterns.First(p => p.Name == "ChaCha20-Poly1305"),
|
||||
AlgorithmPatterns.First(p => p.Name == "SHA-256"),
|
||||
AlgorithmPatterns.First(p => p.Name == "RSA"),
|
||||
AlgorithmPatterns.First(p => p.Name == "ECDSA")
|
||||
};
|
||||
|
||||
foreach (var pattern in conscryptAlgorithms)
|
||||
{
|
||||
assets.Add(CreateAssetFromPattern(component, pattern, $"package:{groupArtifact}",
|
||||
implementationPlatform: "Conscrypt/OpenSSL"));
|
||||
}
|
||||
}
|
||||
else if (groupArtifact.Contains("amazon-corretto-crypto", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Amazon Corretto Crypto Provider
|
||||
var acpAlgorithms = new[]
|
||||
{
|
||||
AlgorithmPatterns.First(p => p.Name == "AES/GCM"),
|
||||
AlgorithmPatterns.First(p => p.Name == "SHA-256"),
|
||||
AlgorithmPatterns.First(p => p.Name == "SHA-512"),
|
||||
AlgorithmPatterns.First(p => p.Name == "RSA"),
|
||||
AlgorithmPatterns.First(p => p.Name == "ECDSA"),
|
||||
AlgorithmPatterns.First(p => p.Name == "ECDH")
|
||||
};
|
||||
|
||||
foreach (var pattern in acpAlgorithms)
|
||||
{
|
||||
assets.Add(CreateAssetFromPattern(component, pattern, $"package:{groupArtifact}",
|
||||
implementationPlatform: "Amazon Corretto Crypto Provider"));
|
||||
}
|
||||
}
|
||||
else if (groupArtifact.Contains("kms", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Cloud KMS libraries
|
||||
assets.Add(new CryptoAsset
|
||||
{
|
||||
Id = $"crypto:{component.Identity.Key}:kms",
|
||||
ComponentKey = component.Identity.Key,
|
||||
AssetType = CryptoAssetType.RelatedCryptoMaterial,
|
||||
AlgorithmName = "KMS",
|
||||
Confidence = 0.9,
|
||||
ImplementationPlatform = groupArtifact.Contains("google") ? "Google Cloud KMS" :
|
||||
groupArtifact.Contains("aws") ? "AWS KMS" :
|
||||
groupArtifact.Contains("azure") ? "Azure Key Vault" : "Cloud KMS",
|
||||
Evidence = ImmutableArray.Create($"package:{groupArtifact}")
|
||||
});
|
||||
}
|
||||
|
||||
return assets;
|
||||
}
|
||||
|
||||
private static CryptoAsset CreateAssetFromPattern(
|
||||
AggregatedComponent component,
|
||||
CryptoAlgorithmPattern pattern,
|
||||
string? evidenceSource = null,
|
||||
string? implementationPlatform = null)
|
||||
{
|
||||
var riskFlags = new List<CryptoRiskFlag>();
|
||||
|
||||
if (pattern.IsDeprecated)
|
||||
{
|
||||
riskFlags.Add(new CryptoRiskFlag
|
||||
{
|
||||
RiskId = "DEPRECATED_ALGORITHM",
|
||||
Severity = CryptoRiskSeverity.Critical,
|
||||
Description = $"{pattern.Name} is deprecated and should not be used",
|
||||
Recommendation = GetDeprecatedRecommendation(pattern.Name)
|
||||
});
|
||||
}
|
||||
|
||||
if (pattern.IsWeak)
|
||||
{
|
||||
riskFlags.Add(new CryptoRiskFlag
|
||||
{
|
||||
RiskId = "WEAK_ALGORITHM",
|
||||
Severity = CryptoRiskSeverity.High,
|
||||
Description = $"{pattern.Name} is considered weak by modern standards",
|
||||
Recommendation = GetWeakRecommendation(pattern.Name)
|
||||
});
|
||||
}
|
||||
|
||||
if (pattern.IsQuantumVulnerable)
|
||||
{
|
||||
riskFlags.Add(new CryptoRiskFlag
|
||||
{
|
||||
RiskId = "QUANTUM_VULNERABLE",
|
||||
Severity = CryptoRiskSeverity.Medium,
|
||||
Description = $"{pattern.Name} is vulnerable to quantum computing attacks",
|
||||
Recommendation = "Consider migration path to post-quantum algorithms (ML-KEM, ML-DSA, SLH-DSA)"
|
||||
});
|
||||
}
|
||||
|
||||
var evidence = new List<string> { $"component:{component.Identity.Key}" };
|
||||
if (evidenceSource != null)
|
||||
{
|
||||
evidence.Add(evidenceSource);
|
||||
}
|
||||
|
||||
var platform = implementationPlatform ?? "Java Cryptography Architecture (JCA)";
|
||||
|
||||
var algorithmProperties = new AlgorithmProperties
|
||||
{
|
||||
Primitive = pattern.Primitive,
|
||||
CryptoFunctions = ImmutableArray.Create(pattern.Function),
|
||||
ClassicalSecurityLevel = pattern.KeySize,
|
||||
ImplementationPlatform = platform,
|
||||
ExecutionEnvironment = ExecutionEnvironment.Software
|
||||
};
|
||||
|
||||
return new CryptoAsset
|
||||
{
|
||||
Id = $"crypto:{component.Identity.Key}:{pattern.Name}",
|
||||
ComponentKey = component.Identity.Key,
|
||||
AssetType = CryptoAssetType.Algorithm,
|
||||
AlgorithmName = pattern.Name,
|
||||
Oid = pattern.Oid,
|
||||
KeySizeBits = pattern.KeySize,
|
||||
Primitive = pattern.Primitive,
|
||||
Functions = ImmutableArray.Create(pattern.Function),
|
||||
ImplementationPlatform = platform,
|
||||
ExecutionEnvironment = ExecutionEnvironment.Software,
|
||||
Confidence = 0.9,
|
||||
Evidence = evidence.ToImmutableArray(),
|
||||
RiskFlags = riskFlags.ToImmutableArray(),
|
||||
CryptoProperties = new CryptoProperties
|
||||
{
|
||||
AssetType = CryptoAssetType.Algorithm,
|
||||
AlgorithmProperties = algorithmProperties,
|
||||
Oid = pattern.Oid
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetDeprecatedRecommendation(string algorithm)
|
||||
{
|
||||
return algorithm.ToUpperInvariant() switch
|
||||
{
|
||||
"MD5" => "Replace with SHA-256 or SHA-3",
|
||||
"SHA1" or "SHA-1" => "Replace with SHA-256 or SHA-3",
|
||||
"DES" => "Replace with AES-256-GCM",
|
||||
"RC4" => "Replace with ChaCha20-Poly1305 or AES-GCM",
|
||||
"RC2" => "Replace with AES-256-GCM",
|
||||
"HMACMD5" => "Replace with HmacSHA256",
|
||||
"HMACSHA1" => "Replace with HmacSHA256",
|
||||
_ => "Replace with a modern algorithm"
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetWeakRecommendation(string algorithm)
|
||||
{
|
||||
return algorithm.ToUpperInvariant() switch
|
||||
{
|
||||
"DESEDE" or "3DES" or "TRIPLEDES" => "Replace with AES-256-GCM",
|
||||
"BLOWFISH" => "Replace with AES-256-GCM or ChaCha20-Poly1305",
|
||||
_ => "Consider using a stronger algorithm"
|
||||
};
|
||||
}
|
||||
|
||||
private sealed record CryptoAlgorithmPattern(
|
||||
string Name,
|
||||
string? Oid,
|
||||
CryptoPrimitive Primitive,
|
||||
CryptoFunction Function,
|
||||
int KeySize,
|
||||
bool IsDeprecated = false,
|
||||
bool IsWeak = false,
|
||||
bool IsQuantumVulnerable = false,
|
||||
bool IsPostQuantum = false);
|
||||
}
|
||||
@@ -16,5 +16,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StellaOps.Scanner.Analyzers.Lang\StellaOps.Scanner.Analyzers.Lang.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Scanner.Emit\StellaOps.Scanner.Emit.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user