Skip to content

Commit 0b01d05

Browse files
Address CodeRabbit review round 7: deterministic BOM, canonical algorithmFamily
- Replace HashMap with BTreeMap for algo_findings and library_algorithms to ensure deterministic component/dependency ordering in CBOM output - Replace custom KNOWN_FAMILIES with official CycloneDX 1.7 algorithmFamily enum (78 canonical entries) and return canonical case via .find() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 5ab4443 commit 0b01d05

1 file changed

Lines changed: 34 additions & 20 deletions

File tree

extlib/cryptoscan/src/cyclonedx.rs

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use serde::{Deserialize, Serialize};
2-
use std::collections::{HashMap, HashSet};
2+
use std::collections::{BTreeMap, HashSet};
33
use uuid::Uuid;
44

55
use crate::crypto_algorithm::CryptoFinding;
@@ -108,10 +108,10 @@ pub fn to_cyclonedx_bom(findings: &[CryptoFinding]) -> CycloneDxBom {
108108
let mut components = Vec::new();
109109
let mut dependencies = Vec::new();
110110
// Key by (ecosystem, library_name) to avoid collapsing libraries across ecosystems
111-
let mut library_algorithms: HashMap<(String, String), Vec<String>> = HashMap::new();
111+
let mut library_algorithms: BTreeMap<(String, String), Vec<String>> = BTreeMap::new();
112112

113113
// Group findings by bom_ref to aggregate detection contexts
114-
let mut algo_findings: HashMap<String, Vec<&CryptoFinding>> = HashMap::new();
114+
let mut algo_findings: BTreeMap<String, Vec<&CryptoFinding>> = BTreeMap::new();
115115
for finding in findings {
116116
let bom_ref = make_bom_ref(&finding.algorithm.name, &finding.algorithm.oid);
117117

@@ -265,25 +265,39 @@ fn make_bom_ref(name: &str, oid: &Option<String>) -> String {
265265
}
266266
}
267267

268-
/// Validate an algorithm family string against the CycloneDX 1.7 registry.
269-
/// Returns `Some(family)` if it's a known value, `None` otherwise.
268+
/// Validate an algorithm family string against the official CycloneDX 1.7 enum.
269+
/// Returns `Some(canonical_form)` if matched, `None` otherwise.
270270
fn valid_algorithm_family(family: &str) -> Option<String> {
271-
const KNOWN_FAMILIES: &[&str] = &[
272-
"AES", "RSA", "EC", "SHA-1", "SHA-2", "SHA-3", "SHAKE",
273-
"3DES", "DES", "Blowfish", "RC4", "RC2", "CAST5", "IDEA",
274-
"Camellia", "SEED", "ARIA", "Serpent", "Twofish", "Threefish",
275-
"ChaCha20-Poly1305", "Salsa20", "HMAC", "CMAC", "GMAC", "KMAC",
276-
"Poly1305", "SipHash", "ECDSA", "EdDSA", "DSA",
277-
"ECDH", "DH", "X25519", "X448", "HKDF", "PBKDF2",
278-
"scrypt", "Argon2", "bcrypt", "BLAKE2", "BLAKE3",
279-
"MD5", "MD4", "RIPEMD", "Whirlpool",
280-
"ML-KEM", "ML-DSA", "SLH-DSA", "FN-DSA",
271+
// Official CycloneDX 1.7 algorithmFamily enum values (case-sensitive in schema)
272+
const CANONICAL_FAMILIES: &[&str] = &[
273+
"3DES", "3GPP-XOR", "A5/1", "A5/2", "AES", "ARIA", "Ascon",
274+
"BLAKE2", "BLAKE3", "BLS", "Blowfish",
275+
"CAMELLIA", "CAST5", "CAST6", "CMAC", "CMEA", "ChaCha", "ChaCha20",
276+
"DES", "DSA",
277+
"ECDH", "ECDSA", "ECIES", "EdDSA", "ElGamal",
278+
"FFDH", "Fortuna",
279+
"GOST",
280+
"HC", "HKDF", "HMAC",
281+
"IDEA", "IKE-PRF",
282+
"KMAC",
283+
"LMS",
284+
"MD2", "MD4", "MD5", "MILENAGE", "ML-DSA", "ML-KEM", "MQV",
285+
"PBES1", "PBES2", "PBKDF1", "PBKDF2", "PBMAC1", "Poly1305",
286+
"RABBIT", "RC2", "RC4", "RC5", "RC6", "RIPEMD",
287+
"RSAES-OAEP", "RSAES-PKCS1", "RSASSA-PKCS1", "RSASSA-PSS",
288+
"SEED", "SHA-1", "SHA-2", "SHA-3", "SLH-DSA", "SNOW3G", "SP800-108",
289+
"Salsa20", "Serpent", "SipHash", "Skipjack",
290+
"TUAK", "Twofish",
291+
"Whirlpool",
292+
"X3DH", "XMSS",
293+
"Yarrow",
294+
"ZUC",
295+
"bcrypt",
281296
];
282-
if KNOWN_FAMILIES.iter().any(|&known| known.eq_ignore_ascii_case(family)) {
283-
Some(family.to_string())
284-
} else {
285-
None
286-
}
297+
CANONICAL_FAMILIES
298+
.iter()
299+
.find(|&&canonical| canonical.eq_ignore_ascii_case(family))
300+
.map(|&canonical| canonical.to_string())
287301
}
288302

289303
fn chrono_timestamp() -> String {

0 commit comments

Comments
 (0)