Cryptography Bill of Materials (CBOM)
Generate a CycloneDX 1.6 Cryptography Bill of Materials — an inventory of the cryptographic assets in your code — with xgrep sbom --cbom.
Cryptography Bill of Materials (CBOM)
xgrep sbom --cbom .
xgrep sbom --cbom -o cbom.json .A Cryptography Bill of Materials (CBOM) is a machine-readable inventory of the cryptographic assets your code uses — algorithms, key material, and protocols — and the relationships between them. It answers a question a vulnerability scan does not: "what cryptography do we use, and where?" That inventory is the starting point for post-quantum-cryptography (PQC) migration and for cryptographic compliance and audit.
xgrep emits a CBOM in the CycloneDX 1.6 format, produced with the upstream CycloneDX Go library, so the output conforms to the official CycloneDX 1.6 schema and is consumable by the broader CycloneDX ecosystem (CBOMkit, CBOM viewers, PQC-migration tooling).
Inventory, not findings
A CBOM is fundamentally different from a vulnerability report. It is a complete
inventory: strong, correctly-used cryptography (for example AES-256-GCM) is
listed as an asset, not flagged as a problem. Each asset is enriched so you can
tell the strong from the weak at a glance — see asset fields
below.
Because of that, a CBOM is generated by the sbom command (it is a bill of
materials, like the dependency SBOM), not by xgrep scan. Detection runs as its
own rule category (cbom) that is off in a normal scan, so it never adds
inventory noise to your findings — and your existing weak-crypto security rules
(weak-cipher, weak-hash, insecure-TLS, …) keep reporting vulnerabilities in
xgrep scan exactly as before.
Scope: crypto only
sbom --cbom and plain sbom produce two distinct bills of materials:
xgrep sbom— a Software BoM: your third-party dependencies.xgrep sbom --cbom— a Cryptography BoM: the cryptographic assets in your source, and only those. It does not include software dependencies.
So --cbom selects the BOM type; it does not add crypto to the dependency
SBOM. It always emits CycloneDX 1.6 JSON, and the dependency-SBOM flags
(--format, --ref, --ecosystem, --direct-only) do not apply to it. Emitting
a single combined document (dependencies and crypto assets together) is a
planned enhancement.
What gets detected
Detection is language- and library-aware. The table below lists the libraries covered and the detected API surface per library:
| Language | Library | Detected API surface |
|---|---|---|
| Java | JCA (javax.crypto / java.security) | Cipher, MessageDigest, Mac, Signature, KeyGenerator, KeyPairGenerator, SecretKeyFactory, SSLContext, CertificateFactory |
| Java | BouncyCastle (lightweight API) | Engines & digests (AESEngine, SHA256Digest, …), HMac |
| Kotlin | JCA | as Java JCA |
| Scala | JCA | as Java JCA |
| Python | stdlib hashlib / hmac | md5/sha1/sha256/sha512, hashlib.new, pbkdf2_hmac, hmac |
| Python | pyca/cryptography (hazmat) | hashes.*, ciphers.algorithms.*, HMAC, RSA/EC/Ed25519/DSA keygen, PBKDF2HMAC/Scrypt/HKDF, x509 certificates |
| Go | crypto/* (stdlib) | aes, des, rc4, md5, sha1, sha256, sha512, hmac, rsa, ecdsa, ed25519, x509/tls certificates |
| Go | golang.org/x/crypto | sha3, chacha20poly1305, pbkdf2, hkdf, bcrypt, scrypt, argon2, blake2b, ripemd160 |
| C# | System.Security.Cryptography (.NET) | hash Create/HashData, Aes/AesGcm/AesCcm/TripleDES/DES/RC2, RSA/ECDsa/ECDiffieHellman/DSA, HMAC*, Rfc2898DeriveBytes (PBKDF2), X509Certificate2 |
| JavaScript / TypeScript | Node.js crypto | createHash, createHmac, createCipheriv, generateKeyPair[Sync], pbkdf2, scrypt, hkdf, createSign |
| JavaScript / TypeScript | CryptoJS, bcrypt, argon2 | CryptoJS.AES/SHA256/MD5/HmacSHA256, bcrypt.hash, argon2.hash |
| Ruby | OpenSSL, Digest, bcrypt | OpenSSL::Cipher/Digest/HMAC/PKey (RSA/EC/DSA)/PKCS5, Digest::*, BCrypt |
| PHP | openssl_*, hash, sodium, password_hash | openssl_encrypt/openssl_pkey_new, hash/hash_hmac/hash_pbkdf2, sodium_*, password_hash (bcrypt/Argon2) |
| Rust | RustCrypto, ring, rsa | sha2/sha1/md-5/sha3, aes-gcm/aes, chacha20poly1305, des, hmac, hkdf, pbkdf2, argon2, bcrypt, rsa, ed25519-dalek, p256 ECDSA, x25519; ring digest/HMAC |
| Swift | CryptoKit, CommonCrypto | SHA256/384/512, Insecure.MD5/SHA1, AES.GCM, ChaChaPoly, HMAC, HKDF, Curve25519, P256/384/521; CC_MD5/CC_SHA256/CCHmac |
| Dart | crypto, PointyCastle | sha256/sha512/sha1/md5/Hmac; PointyCastle engines/digests, PBKDF2/scrypt derivators |
| Elixir | :crypto, Comeonin | :crypto hash/mac/crypto_one_time/generate_key; Bcrypt/Argon2/Pbkdf2 |
| Erlang | crypto | crypto:hash/mac/crypto_one_time/generate_key |
Detected assets span symmetric and asymmetric ciphers, hashes, MACs, signatures,
key-agreement schemes, KDFs, TLS, and X.509 certificates — all four CycloneDX
asset types (algorithm, protocol, related-crypto-material, certificate).
Coverage of additional languages and libraries is expanding. Because a CBOM's
value depends on completeness, treat the absence of an asset as "not yet
detected," not "no crypto."
xgrep also resolves constant references: when an algorithm is passed as an
upper-case constant (e.g. Cipher.getInstance(ALGO) where
static final String ALGO = "AES/GCM/NoPadding"), the constant is resolved to its
string literal within the same file so the real algorithm is inventoried. A
reference that cannot be resolved to a literal is dropped rather than recorded as
an unnamed asset.
Output
The document is a CycloneDX 1.6 BOM whose components are cryptographic-asset
entries. A single detected call becomes a fully-specified asset:
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"metadata": {
"timestamp": "2026-07-01T00:00:00Z",
"component": { "type": "application", "bom-ref": "root:my-project", "name": "my-project" },
"tools": { "components": [{ "type": "application", "name": "xgrep" }] },
},
"components": [
{
"type": "cryptographic-asset",
"bom-ref": "crypto/algorithm/aes-128-gcm@2.16.840.1.101.3.4.1.6",
"name": "AES-128-GCM",
"cryptoProperties": {
"assetType": "algorithm",
"oid": "2.16.840.1.101.3.4.1.6",
"algorithmProperties": {
"primitive": "ae",
"mode": "gcm",
"parameterSetIdentifier": "128",
"cryptoFunctions": ["encrypt", "decrypt", "tag"],
"classicalSecurityLevel": 128,
"nistQuantumSecurityLevel": 1,
},
},
"evidence": {
"occurrences": [
{
"location": "src/Crypto.java",
"line": 12,
"additionalContext": "javax.crypto.Cipher#getInstance",
},
],
},
},
],
"dependencies": [
{
"ref": "root:my-project",
"dependsOn": ["crypto/algorithm/aes-128-gcm@2.16.840.1.101.3.4.1.6"],
},
],
}Understanding an asset
assetType—algorithm,related-crypto-material,protocol, orcertificate.primitive— the algorithm's role:block-cipher,stream-cipher,ae(authenticated encryption),hash,mac,signature,pke,key-agree,kdf, …oid— the algorithm's object identifier, when known.parameterSetIdentifier— key or digest size (e.g.128,256).mode/padding— for ciphers (e.g.gcm,cbc;pkcs5,oaep).classicalSecurityLevel— security strength in bits against classical attacks.nistQuantumSecurityLevel— NIST post-quantum category0–5.0means quantum-vulnerable — the field to scan for when planning PQC migration (RSA/ECDSA/DH are0; broken primitives like MD5/SHA-1 are also0).evidence.occurrences— every source location (file, line) and the detected API that produced the asset.
The dependency graph
Assets are cross-linked in the CycloneDX dependencies graph. The scanned
application depends on each detected asset, and composite algorithms are
decomposed into their parts — for example HMAC-SHA256 dependsOn SHA-256,
and SHA256withRSA dependsOn both SHA-256 and RSA. Identical assets seen at
many call sites collapse to a single component that accumulates all occurrences.
Consuming the CBOM
Write the document to a file and hand it to any CycloneDX-aware tool:
xgrep sbom --cbom -o cbom.json .For example, load it into a CBOM viewer, diff it across releases to track crypto
drift, or feed it to PQC-readiness tooling that flags every
nistQuantumSecurityLevel: 0 asset.