CBOM Example: Three Annotated CycloneDX 1.7 JSON Files (TLS 1.3 Endpoint, Application, HSM Key)

An open wooden card-catalogue drawer pulled out from a wall of labelled index drawers in an archive.

A CBOM example is the quickest way to understand what a cryptography bill of materials actually records. This post gives three worked examples in CycloneDX 1.7 JSON: a TLS 1.3 endpoint that uses hybrid post-quantum key exchange, an application that uses algorithms through a cryptographic library, and a signing key held in a hardware security module (HSM). Every field is explained in plain English, along with what it tells you about quantum exposure.

Each example is a complete CycloneDX document, and each has been validated against the official CycloneDX 1.7 JSON schema (release 1.7.2). The examples are illustrative: the hosts, keys and serial numbers are invented, and they are not the output of any product. For what a CBOM is and why it matters, see what is a cryptography bill of materials. For how CBOM became part of CycloneDX, see CBOM and CycloneDX.

The building blocks

Five parts of the CycloneDX format carry almost all of a CBOM:

  • Components of type cryptographic-asset. Every algorithm, certificate, protocol and key is a component, alongside the applications, libraries and devices an ordinary SBOM already lists.
  • cryptoProperties.assetType. The schema allows four values: algorithm, certificate, protocol and related-crypto-material (keys, tokens, secrets and similar). Each value unlocks its own block of properties.
  • bom-ref. A unique identifier for each component inside the document. Every relationship in a CBOM is expressed by pointing at a bom-ref.
  • Dependencies. dependsOn says one component uses another. provides, added in CycloneDX 1.6, says a component implements something. The CycloneDX guide is precise about the difference: “A component that implements another component does not imply that the implementation is in use.”
  • Security levels. classicalSecurityLevel records classical strength in bits. nistQuantumSecurityLevel records the NIST post-quantum security category, where categories 1, 3 and 5 are defined by comparison with key search on AES-128, AES-192 and AES-256. The schema states: “A value of 0 indicates that none of the categories are met.”

CycloneDX 1.7, released on 21 October 2025, added a standardised list of algorithm families and a list of elliptic curves. The algorithmFamily and ellipticCurve fields must use values from those lists, and the older free-text curve field is deprecated. The examples below use the registry values throughout.

Example 1: a TLS 1.3 endpoint with hybrid key exchange

A public web server negotiates TLS 1.3 with the cipher suite TLS_AES_256_GCM_SHA384 and the hybrid key exchange group X25519MLKEM768. Its certificate carries an RSA-2048 key.

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.7",
  "version": 1,
  "components": [
    {
      "type": "cryptographic-asset",
      "bom-ref": "protocol/tls13-www-example-com-443",
      "name": "TLS 1.3 on www.example.com:443",
      "cryptoProperties": {
        "assetType": "protocol",
        "protocolProperties": {
          "type": "tls",
          "version": "1.3",
          "cipherSuites": [
            {
              "name": "TLS_AES_256_GCM_SHA384",
              "algorithms": [
                "algorithm/aes-256-gcm",
                "algorithm/sha-384"
              ],
              "identifiers": [
                "0x13,0x02"
              ],
              "tlsGroups": [
                "X25519MLKEM768"
              ],
              "tlsSignatureSchemes": [
                "rsa_pss_rsae_sha256"
              ]
            }
          ],
          "relatedCryptographicAssets": [
            {
              "type": "algorithm",
              "ref": "algorithm/x25519mlkem768"
            },
            {
              "type": "certificate",
              "ref": "certificate/www-example-com"
            }
          ]
        }
      }
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "algorithm/x25519mlkem768",
      "name": "X25519MLKEM768",
      "cryptoProperties": {
        "assetType": "algorithm",
        "algorithmProperties": {
          "primitive": "combiner",
          "executionEnvironment": "software-plain-ram",
          "cryptoFunctions": [
            "keyderive"
          ]
        }
      }
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "algorithm/ml-kem-768",
      "name": "ML-KEM-768",
      "cryptoProperties": {
        "assetType": "algorithm",
        "algorithmProperties": {
          "algorithmFamily": "ML-KEM",
          "primitive": "kem",
          "parameterSetIdentifier": "768",
          "executionEnvironment": "software-plain-ram",
          "cryptoFunctions": [
            "keygen",
            "encapsulate",
            "decapsulate"
          ],
          "nistQuantumSecurityLevel": 3
        },
        "oid": "2.16.840.1.101.3.4.4.2"
      }
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "algorithm/x25519",
      "name": "x25519",
      "cryptoProperties": {
        "assetType": "algorithm",
        "algorithmProperties": {
          "algorithmFamily": "ECDH",
          "ellipticCurve": "other/Curve25519",
          "primitive": "key-agree",
          "executionEnvironment": "software-plain-ram",
          "cryptoFunctions": [
            "keygen",
            "keyderive"
          ],
          "nistQuantumSecurityLevel": 0
        },
        "oid": "1.3.101.110"
      }
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "algorithm/aes-256-gcm",
      "name": "AES-256-GCM",
      "cryptoProperties": {
        "assetType": "algorithm",
        "algorithmProperties": {
          "algorithmFamily": "AES",
          "primitive": "ae",
          "parameterSetIdentifier": "256",
          "mode": "gcm",
          "executionEnvironment": "software-plain-ram",
          "cryptoFunctions": [
            "encrypt",
            "decrypt",
            "tag"
          ],
          "classicalSecurityLevel": 256,
          "nistQuantumSecurityLevel": 5
        },
        "oid": "2.16.840.1.101.3.4.1.46"
      }
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "algorithm/sha-384",
      "name": "SHA-384",
      "cryptoProperties": {
        "assetType": "algorithm",
        "algorithmProperties": {
          "algorithmFamily": "SHA-2",
          "primitive": "hash",
          "parameterSetIdentifier": "384",
          "executionEnvironment": "software-plain-ram",
          "cryptoFunctions": [
            "digest"
          ]
        },
        "oid": "2.16.840.1.101.3.4.2.2"
      }
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "certificate/www-example-com",
      "name": "www.example.com",
      "cryptoProperties": {
        "assetType": "certificate",
        "certificateProperties": {
          "serialNumber": "4F2A9C1E7B30D85A",
          "subjectName": "CN = www.example.com",
          "issuerName": "CN = Example Issuing CA, O = Example Ltd, C = GB",
          "notValidBefore": "2026-09-01T00:00:00Z",
          "notValidAfter": "2027-03-01T23:59:59Z",
          "certificateFormat": "X.509",
          "certificateFileExtension": "pem",
          "certificateState": [
            {
              "state": "active"
            }
          ],
          "relatedCryptographicAssets": [
            {
              "type": "algorithm",
              "ref": "algorithm/rsa-pkcs1-1.5-sha-256-2048"
            },
            {
              "type": "publicKey",
              "ref": "key/www-example-com-rsa-2048"
            }
          ]
        }
      }
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "algorithm/rsa-pkcs1-1.5-sha-256-2048",
      "name": "RSA-PKCS1-1.5-SHA-256-2048",
      "cryptoProperties": {
        "assetType": "algorithm",
        "algorithmProperties": {
          "algorithmFamily": "RSASSA-PKCS1",
          "primitive": "signature",
          "parameterSetIdentifier": "2048",
          "padding": "pkcs1v15",
          "executionEnvironment": "software-plain-ram",
          "cryptoFunctions": [
            "verify"
          ],
          "classicalSecurityLevel": 112,
          "nistQuantumSecurityLevel": 0
        },
        "oid": "1.2.840.113549.1.1.11"
      }
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "key/www-example-com-rsa-2048",
      "name": "RSA-2048 public key, www.example.com",
      "cryptoProperties": {
        "assetType": "related-crypto-material",
        "relatedCryptoMaterialProperties": {
          "type": "public-key",
          "state": "active",
          "size": 2048,
          "format": "DER"
        },
        "oid": "1.2.840.113549.1.1.1"
      }
    }
  ],
  "dependencies": [
    {
      "ref": "algorithm/x25519mlkem768",
      "dependsOn": [
        "algorithm/ml-kem-768",
        "algorithm/x25519"
      ]
    }
  ]
}

What each part records:

  • The protocol component. protocolProperties records the protocol type and version, the cipher suite by name and by its IANA identifier (0x13,0x02), the negotiated key exchange group in tlsGroups, and the handshake signature scheme in tlsSignatureSchemes. The cipher suite’s algorithms list points at the AES-256-GCM and SHA-384 components. relatedCryptographicAssets links the protocol to the hybrid group and to the certificate.
  • The hybrid group. X25519MLKEM768 is defined in RFC 10024, published in August 2026, which combines X25519 ECDH with ML-KEM-768. It is recorded as an algorithm with the primitive combiner and a dependsOn relationship to its two parts. This is the pattern the CycloneDX guide uses for hybrid schemes.
  • The two halves. ML-KEM-768 is in NIST security category 3, as stated in FIPS 203, so it carries nistQuantumSecurityLevel 3. X25519 carries 0. No level is set on the combiner itself: an assessor reads the levels of its parts, and the protection against a future quantum attack comes from the ML-KEM half.
  • The certificate. certificateProperties records subject, issuer, validity dates and state, and links to the signature algorithm and the public key. The signature is RSA PKCS#1 v1.5 with SHA-256, at a classical strength of 112 bits (NIST SP 800-57 Part 1, Table 2) and nistQuantumSecurityLevel 0.
  • Two RSA signature types. The certificate is signed with PKCS#1 v1.5, while the handshake uses rsa_pss_rsae_sha256. TLS 1.3 requires this split. RFC 9846, the current TLS 1.3 specification, says the PKCS#1 v1.5 values “refer solely to signatures which appear in certificates”.

Reading it for quantum exposure. The key exchange is hybrid, so recorded traffic from this endpoint is protected against later decryption by a quantum computer for as long as ML-KEM-768 holds. The authentication is not. Certificate and handshake signatures both rely on RSA-2048. The record shows the split plainly: the key exchange has moved to post-quantum protection, and the signatures have not. The validity dates matter too. In the guide’s words, “An RSA certificate expiring in one week poses less cryptographic risk than the same certificate expiring in 20 years.”

Example 2: an application, a library and the algorithms it uses

A payments service encrypts stored tokens with AES-256-GCM and wraps data keys with RSA-OAEP. Both algorithms come from a cryptographic library, and source code assessment found the call site.

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.7",
  "version": 1,
  "components": [
    {
      "type": "application",
      "bom-ref": "app/payments-service",
      "name": "payments-service",
      "version": "4.2.0",
      "evidence": {
        "occurrences": [
          {
            "location": "src/main/java/com/example/payments/TokenVault.java",
            "line": 87,
            "symbol": "Cipher.getInstance"
          }
        ]
      }
    },
    {
      "type": "library",
      "bom-ref": "lib/example-crypto-library",
      "name": "example-crypto-library",
      "version": "2.4.1"
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "algorithm/aes-256-gcm",
      "name": "AES-256-GCM",
      "cryptoProperties": {
        "assetType": "algorithm",
        "algorithmProperties": {
          "algorithmFamily": "AES",
          "primitive": "ae",
          "parameterSetIdentifier": "256",
          "mode": "gcm",
          "executionEnvironment": "software-plain-ram",
          "cryptoFunctions": [
            "encrypt",
            "decrypt",
            "tag"
          ],
          "classicalSecurityLevel": 256,
          "nistQuantumSecurityLevel": 5
        },
        "oid": "2.16.840.1.101.3.4.1.46"
      }
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "algorithm/rsa-oaep-sha-256-2048",
      "name": "RSA-OAEP-SHA-256-2048",
      "cryptoProperties": {
        "assetType": "algorithm",
        "algorithmProperties": {
          "algorithmFamily": "RSAES-OAEP",
          "primitive": "pke",
          "parameterSetIdentifier": "2048",
          "padding": "oaep",
          "executionEnvironment": "software-plain-ram",
          "cryptoFunctions": [
            "encrypt",
            "decrypt"
          ],
          "classicalSecurityLevel": 112,
          "nistQuantumSecurityLevel": 0
        },
        "oid": "1.2.840.113549.1.1.7"
      }
    }
  ],
  "dependencies": [
    {
      "ref": "app/payments-service",
      "dependsOn": [
        "lib/example-crypto-library",
        "algorithm/aes-256-gcm",
        "algorithm/rsa-oaep-sha-256-2048"
      ]
    },
    {
      "ref": "lib/example-crypto-library",
      "provides": [
        "algorithm/aes-256-gcm",
        "algorithm/rsa-oaep-sha-256-2048"
      ]
    }
  ]
}
  • Evidence. The application component carries an evidence.occurrences entry with the file, line and symbol where the cryptography was found. That is what lets an engineer go straight to the code that needs changing.
  • provides and dependsOn together. The library provides both algorithms, which says only that it implements them. The application dependsOn both algorithms, which says they are in use. A library that provides fifty algorithms does not create fifty migration items. The application’s actual use creates two.
  • The algorithms. AES-256-GCM is recorded with mode gcm, a classical strength of 256 bits and nistQuantumSecurityLevel 5, the category defined by AES-256 key search. RSA-OAEP-SHA-256-2048 is recorded with padding oaep, 112 bits classical and level 0.

Reading it for quantum exposure. The symmetric layer can stay. The RSA-OAEP key wrapping is the migration item, and because it protects keys for stored data, it is also a harvest-now-decrypt-later concern: anyone holding a copy of the wrapped keys could unwrap them once RSA-2048 falls.

Example 3: a code signing key held in an HSM

A code signing key lives in a hardware security module and signs releases with RSA-PSS.

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.7",
  "version": 1,
  "components": [
    {
      "type": "device",
      "bom-ref": "device/example-hsm-01",
      "name": "example-hsm-01",
      "version": "7.1"
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "key/code-signing-2026",
      "name": "Code signing key 2026",
      "cryptoProperties": {
        "assetType": "related-crypto-material",
        "relatedCryptoMaterialProperties": {
          "type": "private-key",
          "id": "code-signing-2026",
          "state": "active",
          "size": 3072,
          "creationDate": "2026-01-12T09:00:00Z",
          "activationDate": "2026-01-15T00:00:00Z",
          "expirationDate": "2029-01-15T00:00:00Z",
          "securedBy": {
            "mechanism": "HSM"
          },
          "relatedCryptographicAssets": [
            {
              "type": "algorithm",
              "ref": "algorithm/rsa-pss-sha-256-3072"
            }
          ]
        }
      }
    },
    {
      "type": "cryptographic-asset",
      "bom-ref": "algorithm/rsa-pss-sha-256-3072",
      "name": "RSA-PSS-SHA-256-3072",
      "cryptoProperties": {
        "assetType": "algorithm",
        "algorithmProperties": {
          "algorithmFamily": "RSASSA-PSS",
          "primitive": "signature",
          "parameterSetIdentifier": "3072",
          "executionEnvironment": "hardware",
          "certificationLevel": [
            "fips140-3-l3"
          ],
          "cryptoFunctions": [
            "sign"
          ],
          "classicalSecurityLevel": 128,
          "nistQuantumSecurityLevel": 0
        },
        "oid": "1.2.840.113549.1.1.10"
      }
    }
  ],
  "dependencies": [
    {
      "ref": "device/example-hsm-01",
      "provides": [
        "algorithm/rsa-pss-sha-256-3072"
      ]
    }
  ]
}
  • The key. The key is recorded as related-crypto-material of type private-key, with size, dates and a state. The schema defines state as “The key state as defined by NIST SP 800-57.” securedBy records the HSM as the protection mechanism.
  • No key material. The schema has a value field. For a private key, leave it out. A CBOM is an inventory of metadata and is shared more widely than the keys it describes.
  • The algorithm. RSA-PSS-SHA-256-3072 is recorded with executionEnvironment set to hardware, a certification level, a classical strength of 128 bits (SP 800-57 Part 1, Table 2) and nistQuantumSecurityLevel 0. The HSM device component provides the algorithm.

Reading it for quantum exposure. Signatures are not exposed to harvest now, decrypt later in the way encrypted data is. A forged signature needs a quantum computer at the time of the forgery. What makes this key a priority is its reach and its lifetime: it expires in 2029, and software it signs may be verified long after that. Knowing that it sits in an HSM with a recorded certification level also tells the migration team that the HSM’s own post-quantum support is a prerequisite.

The three examples at a glance

AssetNIST quantum levelReading
ML-KEM-768 (in X25519MLKEM768)3Post-quantum key exchange in place
X25519 (in X25519MLKEM768)0Classical half of the hybrid
AES-256-GCM5Symmetric, can stay
RSA-2048 certificate signature0Authentication still to migrate
RSA-OAEP-SHA-256-20480Key wrapping to migrate, stored-data exposure
RSA-PSS-SHA-256-3072 in HSM0Long-lived signing key to migrate, HSM support is a prerequisite

Common mistakes when writing a CBOM

  • Free-text algorithm and curve names. Use the CycloneDX registry values for algorithmFamily and ellipticCurve, such as ECDH and other/Curve25519, rather than whatever string a tool printed.
  • Unchecked OIDs. Object identifiers are easy to copy wrongly. Check them against the registry that assigned them: NIST’s Computer Security Objects Register for AES, SHA-2, ML-KEM and ML-DSA, RFC 8017 for RSA, and RFC 8410 for X25519. If you cannot confirm an OID, omit the field rather than guess.
  • Treating provides as use. An inventory built only from what libraries implement overstates the work. Record use with dependsOn.
  • Guessing. Most of the enumerations in the cryptographic properties, such as primitive, mode and executionEnvironment, include unknown. A recorded unknown can be followed up, but a guess hides the gap.
  • Secrets in the BOM. Record that a key exists and how it is protected, not its value.
  • Skipping validation. The schema enforces the registry values. A CBOM that fails validation will fail in the tools that consume it.

Where CBOM requirements are heading

In the US, OMB memorandum M-26-15 says an agency’s automated cryptographic inventory “should populate a central Cryptographic Bill of Materials (CBOM)”. Executive Order 14412 directs CISA, in coordination with NIST, to publish guidance on the minimum elements of a CBOM, due about 270 days after the order, around 19 March 2027. Until that guidance exists, CycloneDX is the published format to build on. The examples in this post will need checking against those minimum elements once they are released. See what OMB M-26-15 and EO 14412 mean for suppliers for the full timeline.

How a CBOM feeds the ECEM lifecycle

Enterprise Cryptographic Exposure Management (ECEM) is a continuous six-stage lifecycle: Discover, Inventory, Assess, Prioritise, Transition, Monitor. A CBOM is the Inventory stage written down in a form machines can read. The fields in these examples feed the stages that follow it: security levels and certificate dates feed Assess, dependencies and evidence feed Prioritise by showing what is actually in use and where, and the same document regenerated over time feeds Monitor.

Quantum Sentinel builds a living Enterprise CBOM from discovery across the estate and exports it as CycloneDX 1.7. The examples in this post were written by hand to illustrate the format and are not Quantum Sentinel output. The cryptographic coverage page lists what the platform discovers.

Frequently asked questions

What does a CBOM example look like?

A CBOM in CycloneDX is a CycloneDX document, usually JSON, whose components include cryptographic assets. Each asset has a cryptoProperties block with an assetType of algorithm, certificate, protocol or related-crypto-material, plus properties such as algorithm family, parameter set, security levels and OID. Dependencies link assets to the applications, libraries and devices that use or provide them.

Which CycloneDX version supports CBOM?

CBOM was introduced in CycloneDX 1.6, released on 9 April 2024. CycloneDX 1.7, released on 21 October 2025, added standardised lists of algorithm families and elliptic curves. The current 1.7 patch release is 1.7.2.

How do you record hybrid key exchange such as X25519MLKEM768 in a CBOM?

Record each half as its own algorithm component, ML-KEM-768 and X25519, then record the hybrid as an algorithm with the primitive combiner and a dependsOn relationship to both halves. In a TLS protocol component, the hybrid group name also appears in the cipher suite’s tlsGroups list.

What does nistQuantumSecurityLevel 0 mean?

It means the algorithm meets none of NIST’s post-quantum security categories. RSA, ECDH, ECDSA and X25519 are recorded as 0. Post-quantum and symmetric algorithms are recorded by category, for example 3 for ML-KEM-768 and 5 for AES-256.

Should a CBOM contain private keys?

No. A CBOM should record that a key exists, its type, size, state, dates and how it is protected, for example in an HSM. The key material itself should stay where it is protected.

Sources: CycloneDX, specification and JSON schemas (release 1.7.2, including bom-1.7.schema.json and cryptography-defs.schema.json); OWASP CycloneDX, Authoritative Guide to CBOM; CycloneDX, v1.7 release announcement (21 October 2025) and v1.6 release announcement (9 April 2024); IETF, RFC 10024 and RFC 9846; IANA, TLS parameters; NIST, FIPS 203, post-quantum security categories, SP 800-57 Part 1 Rev. 5 and the Computer Security Objects Register.

Further reading: what a cryptography bill of materials is, how CBOM became part of CycloneDX, what Enterprise Cryptographic Exposure Management is and the Quantum Sentinel cryptographic coverage page.

Scroll to Top