> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scanoss.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Build a cryptographic inventory (CBOM) for post-quantum readiness

> Use Crypto Finder to inventory the cryptography in your code and dependencies, export a CycloneDX 1.7 CBOM, list the quantum-vulnerable algorithms you will need to migrate, and fail the build on broken algorithms.

## Goal

Produce a cryptographic inventory of a codebase:

* a findings file with every place your code (and, optionally, your dependencies) uses
  cryptography
* a CycloneDX 1.7 Cryptography Bill of Materials (CBOM) to share with security, compliance,
  or customers
* two short reports: the quantum-vulnerable public-key algorithms you will have to migrate,
  and any broken algorithms you should remove now

## When to use it

* You are planning a migration to post-quantum cryptography and need to know where your code
  uses RSA, elliptic-curve, and Diffie-Hellman algorithms.
* A customer or a framework asks for a cryptographic inventory or a CBOM.
* You want to stop new uses of broken algorithms such as MD5, SHA-1, DES, or RC4.

## Prerequisites

* Docker, to run the Crypto Finder image, which includes the scanning engine. To run Crypto
  Finder without Docker, install the binary and OpenGrep as described in
  [Installation](/en/latest/cli/crypto-finder/installation).
* `SCANOSS_API_KEY`, used to download the SCANOSS-maintained detection rules
* `jq`

## The script

Save this as `ci/crypto-inventory.sh` and run it from the repository root.

```bash theme={null}
#!/usr/bin/env bash
# Build a cryptographic inventory and CBOM with Crypto Finder.
#
# Environment:
#   SCANOSS_API_KEY       required for SCANOSS remote rules
#   CRYPTO_FINDER_IMAGE   image to run (default ghcr.io/scanoss/crypto-finder:latest)
#   FAIL_ON_BROKEN        "true" (default) fails when broken algorithms are found
set -euo pipefail

IMAGE="${CRYPTO_FINDER_IMAGE:-ghcr.io/scanoss/crypto-finder:latest}"
FAIL_ON_BROKEN="${FAIL_ON_BROKEN:-true}"
OUT="crypto-inventory"
mkdir -p "$OUT"

# 1. Scan the code. Errors are printed to stderr as one JSON object.
docker run --rm \
  -v "$PWD:/workspace/code:ro" \
  -v "$PWD/$OUT:/workspace/output" \
  -e SCANOSS_API_KEY \
  "$IMAGE" \
  scan --exclude "$OUT/" --error-format json \
       --output /workspace/output/crypto-findings.json /workspace/code

# 2. Convert the findings to a CycloneDX 1.7 CBOM.
docker run --rm \
  -v "$PWD/$OUT:/workspace/output" \
  "$IMAGE" \
  convert /workspace/output/crypto-findings.json --output /workspace/output/cbom.cdx.json

findings="$OUT/crypto-findings.json"

# 3. Inventory: how often each algorithm family is used.
echo "Algorithm families:"
jq -r '
  [.findings[].cryptographic_assets[] | .metadata.algorithmFamily // .metadata.assetType // "unknown"]
  | group_by(.) | map({family: .[0], count: length}) | sort_by(-.count)[]
  | "  \(.count)\t\(.family)"
' "$findings" | tee "$OUT/families.txt"

# 4. Post-quantum report: public-key algorithms broken by a quantum computer.
jq -r '
  .findings[] | .file_path as $file
  | .cryptographic_assets[]
  | select((.metadata.algorithmFamily // "") | test("^(RSA|DSA|ECDSA|ECDH|ECIES|EdDSA|FFDH|DH)"; "i"))
  | "\($file):\(.start_line)\t\(.metadata.algorithmFamily)\t\(
      if .source == "dependency" then "dependency \(.dependency_info.module)@\(.dependency_info.version)"
      else "own code" end)"
' "$findings" > "$OUT/quantum-vulnerable.tsv"
echo "Quantum-vulnerable uses: $(wc -l < "$OUT/quantum-vulnerable.tsv")"

# 5. Gate: broken algorithms.
jq -r '
  .findings[] | .file_path as $file
  | .cryptographic_assets[]
  | select((.metadata.algorithmFamily // "") | test("^(MD4|MD5|SHA-?1|DES|3DES|RC4)$"; "i"))
  | "\($file):\(.start_line)\t\(.metadata.algorithmFamily)"
' "$findings" > "$OUT/broken.tsv"

if [ -s "$OUT/broken.tsv" ]; then
  echo "Broken algorithms in use:"
  cat "$OUT/broken.tsv"
  [ "$FAIL_ON_BROKEN" = "true" ] && exit 2
fi
echo "CBOM written to $OUT/cbom.cdx.json"
```

## What each step does

1. **Scan.** Crypto Finder detects the languages in the repository, downloads the matching
   SCANOSS detection rules (cached for 7 days), and runs them. The script mounts the repository
   read-only.
   `--exclude` keeps the script's own output folder out of the scan. `--error-format json`
   prints any failure as one JSON object with a stable `code`, which is easier to read in CI logs
   and to parse.
2. **Convert.** `convert` turns the findings into a CycloneDX 1.7 CBOM and validates it against
   the CycloneDX schema. The CBOM includes only findings with complete metadata, so it can list
   fewer assets than the findings file.
3. **Inventory.** The script counts the findings per algorithm family, such as `AES`, `SHA-2`, or `ECDSA`.
4. **Post-quantum report.** The script lists every use of a public-key family that a large quantum computer
   could break: RSA (including `RSASSA-PKCS1`, `RSASSA-PSS`, `RSAES-OAEP`, and `RSAES-PKCS1`),
   DSA, ECDSA, ECDH, ECIES, EdDSA, and finite-field Diffie-Hellman. These are the uses to
   replace with post-quantum algorithms such as `ML-KEM` and `ML-DSA`, which Crypto Finder also
   reports.
5. **Gate.** The script lists uses of broken algorithms and fails the build if it finds any.

The family lists in steps 4 and 5 are this recipe's policy, not a Crypto Finder feature. Change
the regular expressions to match your own cryptography policy.

## What the output means

| File | Contains |
| - | - |
| `crypto-findings.json` | Every finding: file, lines, matched code, the rules that matched, and metadata such as `assetType`, `algorithmFamily`, `algorithmPrimitive`, and `algorithmMode`. See [Output formats](/en/latest/cli/crypto-finder/output-formats). |
| `cbom.cdx.json` | CycloneDX 1.7 CBOM: one `cryptographic-asset` component per algorithm, protocol, certificate, or key material, with `cryptoProperties` and the locations where it occurs |
| `families.txt` | Number of findings per algorithm family |
| `quantum-vulnerable.tsv` | One line per quantum-vulnerable use: location, family, and whether it is in your code or a dependency |
| `broken.tsv` | One line per broken algorithm use |

A sample of `quantum-vulnerable.tsv`:

```
src/auth/token.go:42	ECDSA	own code
src/tls/handshake.go:118	ECDH	own code
```

Each line is one migration task. It gives the location and the algorithm to replace.

## How it fails the pipeline

| Exit code | Meaning |
| - | - |
| `0` | Inventory produced, no broken algorithms (or `FAIL_ON_BROKEN=false`) |
| `1` | Crypto Finder failed. Read the JSON error on stderr, for example `rules_load_failed` or `scanner_timeout`. |
| `2` | Broken algorithms found |

<Note>
  Crypto Finder also has `--fail-on-findings`, which exits `1` when it finds any
  cryptography. That is useful to keep cryptography out of a component that must not have any.
  For an inventory it is too broad, because almost every codebase uses some cryptography, so this
  recipe filters the findings with `jq` instead. With `--error-format json`, a failure caused by
  `--fail-on-findings` has the code `findings_detected`, so you can tell it apart from a tool
  error.
</Note>

## Include your dependencies

In most projects, the bulk of the cryptography is in third-party libraries. To scan your dependencies as well, use
the `latest-deps` image, which includes the language toolchains needed to resolve them, and add
`--scan-dependencies`:

```bash theme={null}
docker run --rm \
  -v "$PWD:/workspace/code:ro" \
  -v "$PWD/crypto-inventory:/workspace/output" \
  -e SCANOSS_API_KEY \
  ghcr.io/scanoss/crypto-finder:latest-deps \
  scan --scan-dependencies --exclude "crypto-inventory/" --error-format json \
       --output /workspace/output/crypto-findings.json /workspace/code
```

Dependency scanning supports Go, Java (Maven and Gradle), Python, Rust, and Node (npm). Findings
in dependencies have `"source": "dependency"` and a `dependency_info` object with the module and
version. The post-quantum report above already labels them. See
[Dependency scanning](/en/latest/cli/crypto-finder/dependency-scanning) for reachability and
call-chain analysis, which tells you whether your code reaches a dependency's cryptography.

## Scan only what a pull request changed

To check a pull request for new broken algorithms without re-reporting the whole codebase, scope
detection to the changed files:

```bash theme={null}
git diff --name-only "origin/main...HEAD" > changed.txt
crypto-finder scan --detect-paths-from changed.txt --error-format json \
  --output crypto-findings.json .
```

Then run step 5 of the script on `crypto-findings.json`. Crypto Finder checks only the listed
files, but it still reads the rest of the repository, so the results for those files match a full
scan.
`--detect-paths-from` needs the default OpenGrep scanner.

## Keep the inventory over time

* Run the full script on a schedule or on each release, and store the outputs with the release.
* Compare `families.txt` and `quantum-vulnerable.tsv` between runs to track migration progress.
* Pin the image to a version tag in CI rather than `latest`, so a new release cannot change your
  inventory without a code change.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.