Repository navigation
pq-verify v2.6.5
pq-verify v2.6.5
Now on PyPI, with SARIF output and a GitHub Action — pq-verify can run as a
CI gate rather than something someone remembers to invoke.
pip install "pq-verify[full]"
pq-verify --acvp-all # 855/855, offlineInstallable
pip install pq-verify now works. Previously installation required a git URL,
which is friction for anyone evaluating the tool and a non-starter for most
build systems.
The NIST vectors ship inside the package, so a fresh install verifies
855/855 offline with no configuration — no network, no notebook, no
service. Verified on a bare container with networking blocked.
CI integration
An official GitHub Action. Three lines in any repository that builds an ML-KEM
or ML-DSA implementation:
- uses: bigDSanalyst/pq-verify@v1
with:
library: build/libmlkem768.so
symbol: PQCLEAN_MLKEM768_CLEAN_nttFindings surface as annotations on the pull request diff. fail-on-finding
(default true) fails the build when the transform diverges from the FIPS
reference. Outputs verified, findings and sarif-file for downstream steps.
SARIF 2.1.0 output
pq-verify --audit-so lib.so SYMBOL --sarif results.sarif --json results.json \
--fail-on-findingSARIF is ingested natively by GitHub Code Scanning, DefectDojo, Snyk and AWS
Security Hub. A verifier that reports only to a terminal cannot become part of
a security workflow; this puts findings where a team already looks.
Five rules are reported, each mapped to a specific failure mode:
| Rule | Meaning |
|---|---|
PQV001 |
NTT output diverges from the FIPS reference |
PQV002 |
Freivalds probabilistic check failed |
PQV003 |
Root of unity has the wrong multiplicative order |
PQV004 |
Non-circular known-answer test failed |
PQV005 |
Boundary/edge-case vector failed |
Output validated against the OASIS SARIF 2.1.0 schema.
Packaging fixes
pq_verify.vectorsis now a declared package rather than an implicit data
directory. A future setuptools discovery change could otherwise have shipped
a wheel with no ACVP vectors — which would install cleanly and then fail
every offline verification at runtime.- License metadata moved to the SPDX form (
license = "MIT"plus
license-files); the table form is deprecated and stops working in
February 2027. - Removed dead
*.c/*.cppglobs fromMANIFEST.in. The six field-native
engines are embedded as strings incore.pyand compiled at runtime, so
there are no C source files to package.
Result: the build emits no warnings, and both artifacts pass twine check.
Verification performed
- Clean venv,
pip install "pq-verify[full]"from PyPI → 2.6.5 - 855/855 offline with networking blocked
- 975/975 with
slhdsa=True(adds FIPS 205 keyGen) - 18/18 pytest
- SARIF written and schema-validated from the published wheel
- Action definition validated against GitHub's Actions schema; CI gating
confirmed to exit non-zero on a deliberately corrupted library and zero on a
correct one
Independent audits
Unchanged from 2.6.4 and documented in AUDITS.md: liboqs
(mlkem-native / mldsa-native), PQClean, the pq-crystals reference, and a
BoringSSL vector cross-check — all verify clean, with negative controls that
correctly fail.
MIT · Nicholas Maino (iamweare) · DOI 10.5281/zenodo.21739511