Metadata-Version: 2.4
Name: pqcheck
Version: 0.0.1
Summary: Post-quantum cryptography risk scanner for source code and dependency graphs.
Project-URL: Homepage, https://github.com/Rafael-Ryu/pqcheck
Project-URL: Repository, https://github.com/Rafael-Ryu/pqcheck
Project-URL: Issues, https://github.com/Rafael-Ryu/pqcheck/issues
Author: CryptoCT Founders
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: anpd,cbom,cryptography,lgpd,post-quantum,pqc,sarif,sbom,security,supply-chain
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: cyclonedx-python-lib<11,>=8.5
Requires-Dist: jsonschema<5,>=4.23
Requires-Dist: lxml<7,>=5.3
Requires-Dist: packageurl-python<1,>=0.16
Requires-Dist: pathspec<1,>=0.12
Requires-Dist: pydantic-settings<3,>=2.6
Requires-Dist: pydantic<3,>=2.11
Requires-Dist: pyyaml<7,>=6.0
Requires-Dist: rich<15,>=13.9
Requires-Dist: tree-sitter-go<0.26,>=0.23
Requires-Dist: tree-sitter-java<0.26,>=0.23
Requires-Dist: tree-sitter<0.26,>=0.23
Requires-Dist: typer<1,>=0.15
Provides-Extra: dev
Requires-Dist: hypothesis<7,>=6.115; extra == 'dev'
Requires-Dist: mypy<2,>=1.13; extra == 'dev'
Requires-Dist: pytest-cov<8,>=6.0; extra == 'dev'
Requires-Dist: pytest-xdist<4,>=3.6; extra == 'dev'
Requires-Dist: pytest<9,>=8.3; extra == 'dev'
Requires-Dist: ruff<1,>=0.7; extra == 'dev'
Requires-Dist: syrupy<5,>=4.7; extra == 'dev'
Requires-Dist: types-jsonschema; extra == 'dev'
Requires-Dist: types-lxml; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Provides-Extra: sigstore
Requires-Dist: sigstore<5,>=4; extra == 'sigstore'
Description-Content-Type: text/markdown

# pqcheck

Generate a Cryptography Bill of Materials (CBOM) for your codebase in
seconds, and gate CI on a crypto policy you can read.

`pqcheck` scans source code and dependency lockfiles for cryptographic
algorithm usage — RSA, ECDSA, AES modes, legacy hashes, post-quantum
primitives — and emits a CycloneDX 1.6 CBOM plus SARIF 2.1.0, evaluated
against a versionable YAML policy. It runs on a laptop and in CI with no
server, no account, and no network access during the scan.

Why now: NIST IR 8547 deprecates RSA and ECC by 2030 and disallows them
by 2035. Every migration framework (OMB M-23-02, the EU coordinated
roadmap, FS-ISAC guidance) makes inventory the first step. The existing
open tooling for that step needs a SonarQube server; the commercial
options start at enterprise pricing. This is the `pip install` version.

**Status: pre-release.** v0.1.0 lands on PyPI with Sigstore-signed
wheels. Until then: `uv sync --all-extras && uv run pqcheck --help`.
[Leia em português](README.pt-br.md).

## Quickstart

```console
$ pqcheck scan ./your-repo --policy cryptoct-default
✗ src/auth.py:42 — RSA [banned/critical, confidence high] — Shor — migrate to ML-KEM-768
⚠ src/hash.py:7  — BLAKE2B [default/medium, confidence high]
✓ src/aead.py:12 — AES [approved/info, confidence high]
dependencies: 47 parsed
policy cryptoct-default-1.0.0: 1 fail, 1 warn, 1 allow
```

Machine-readable outputs:

```console
$ pqcheck scan . --policy cryptoct-default --format cbom -o cbom.cdx.json
$ pqcheck scan . --format sarif -o pqcheck.sarif   # imports into GitHub Code Scanning
```

Gate CI (`exit 1` when the policy trips):

```console
$ pqcheck scan . --policy br-bcb-conservative --fail-on policy
$ pqcheck self-audit          # fixed policy, CBOM always written
```

`--fail-on high` gates on base severity instead; `--strict` treats WARN
decisions as failures. A finding's displayed severity is demoted by
detection confidence, but gating always reads the base severity — low
confidence never lets RSA through.

## What it detects

| Surface | Coverage |
|---|---|
| Python source | stdlib `hashlib`, `cryptography` (current + legacy + decrepit paths), `pycryptodome` — via AST, no execution |
| Go source | stdlib `crypto/*` and `golang.org/x/crypto` — union of a bundled `go/types` analyzer (semantic: key sizes, curves, modes) and a tree-sitter pass that also covers GOOS/cgo-gated files, which type resolution cannot see by construction |
| Lockfiles | `pyproject.toml`, `uv.lock`, `requirements.txt`, `pom.xml`, `go.mod`+`go.sum`, `package-lock.json` |

Java is next on the roadmap; it is not in v0.1.

## Policies

Six bundled policies, all plain YAML you can fork:

- `cryptoct-default` / `cryptoct-strict` / `cryptoct-advisory` — the
  general tiers (fail / fail-hard / report-only).
- `br-bcb-conservative` — for Brazilian financial institutions aligning
  their inventory with the cybersecurity controls of Res. CMN 4.893/2021.
- `br-drex-piloto` — the strictest profile, for teams that want new code
  quantum-safe by construction.
- `br-vendor-dd` — advisory profile for vendor due-diligence annexes.

To be clear about the regulatory framing: **no Brazilian regulation
currently mandates a cryptographic inventory or PQC migration.** The BR
profiles anticipate that direction; they do not claim an obligation that
does not exist.

`pqcheck policy show <name>` prints any of them resolved;
`pqcheck policy validate <file>` checks your own against the schema.

## Measured precision

Every HIGH/CRITICAL finding across a 10-repo public corpus (pyjwt,
paramiko, sigstore-python, age, go-jose, smallstep/crypto, …) was
human-adjudicated by reading the flagged line: **230 findings, 0 false
positives**. Protocol, pinned SHAs, and verdicts are in `tests/corpus/`.
The honest caveat: explicit-call detection is precise by construction;
recall (what the scanner misses) is not yet measured — that is the next
corpus iteration.

## Known limitations

- Findings carry no usage context yet: the policy cannot distinguish
  "RSA verifying a third-party webhook" from "RSA encrypting data at
  rest". Context-scoped rules are parsed but deliberately not shipped in
  the bundled policies until detectors emit context.
- No hybrid-scheme detection (X25519MLKEM768 reads as X25519).
- Insecure RNG usage (`math/rand` for keys) is not detected yet.
- Only the repo root's `.gitignore`/`.pqcheckignore` are honored.
- Dependency findings are inventory (`introduces` metadata in the CBOM);
  they do not trip the policy gate in v0.1 — call sites do.

## Development

Requires Python 3.12+ and [`uv`](https://github.com/astral-sh/uv):
`uv sync --all-extras`, then `uv run pytest`, `uv run ruff check .`,
`uv run mypy`. See [CONTRIBUTING.md](CONTRIBUTING.md).

## License

Apache-2.0. See [SECURITY.md](SECURITY.md) for the vulnerability
disclosure process and the honest list of classical crypto this project
itself transitively depends on.
