Skip to main content

certanix-verify

Verify a Certanix evidence pack offline. The standard library plus two pinned dependencies, no network, no cosign binary, no transparency-log lookup, and nothing from the Certanix platform.

The two dependencies, and why (from 0.6.0):

  • cryptography checks signatures (ECDSA, RSA) and X.509 certificates.
  • asn1crypto, pure Python with no compiled code, parses ASN.1: the RFC 3161 timestamp tokens and RFC 4998 evidence records of the Certanix Vault, which cryptography cannot read. Hand-written DER parsing was rejected as security-sensitive code with no second reviewer, and a separate package was rejected because a person checking a disclosure in 2036 should need to install one tool.

Quickstart

pip install certanix-verify
certanix-verify verify evidence-pack.json --key cosign.pub
echo $?          # 0 = verified; any other value is the failure class (see below)

What it checks, and what it does not

It checks that the pack's canonical bytes — recomputed from the document exactly as you supply it — match the detached signature made by the key you pass in, that the pack satisfies the evidence-pack schema, and that it does not claim a capability its own recorded capability gate denies.

It does not tell you whose key that is. A signature verifies against whatever key you hand it, so confirm the key's fingerprint against an out-of-band source (a Certanix deck appendix, printed collateral, a channel you already trust) before trusting what a green result means. A verifier that implied otherwise would be lying by omission.

Exit codes

The exit code is the failure class, so a script can branch on why verification failed without parsing text:

Code Class Meaning
0 OK Signature valid over the canonical bytes; schema valid; no gate violation.
1 USAGE Could not begin: unreadable pack, missing key, bad invocation. Says nothing about the pack.
2 MALFORMED_INPUT Not parseable as a JSON object (e.g. truncated).
3 SCHEMA_INVALID Parses, but violates the schema: missing required field, unknown field, value outside a closed vocabulary.
4 UNSUPPORTED_SCHEMA_VERSION A schema version this verifier does not know. Refused rather than guessed at.
5 SIGNATURE_MISSING The pack carries no signature — an unsigned pack, not a failed check.
6 SIGNATURE_MALFORMED A signature is present but its container is not decodable.
7 SIGNATURE_MISMATCH The cryptographic check failed: these are not the bytes that were signed. The tamper class.
8 KEY_MISMATCH The signature names a different signer than the key supplied.
9 GATE_VIOLATION Signature and schema are valid, but the pack claims a capability its recorded gate state denies.
10 EVIDENCE_MISMATCH vault only: the evidence record does not cover these bytes. They changed after they were timestamped.
11 TIMESTAMP_INVALID vault only: the RFC 3161 token is not valid (modified, or its signature fails).
12 TSA_UNTRUSTED vault only: the token's signer does not chain to a trust anchor you supplied, is not a time-stamping certificate, or was not valid when the token was issued.
13 TSA_EXPIRED vault only: the time-stamping certificate has expired at the verification time and nothing in the record renews it.

Vault evidence records (0.6.0)

certanix-verify vault evidence-record-0001.ers \
    --data artefact --data manifest.json --tsa-root tsa-root.pem [--at 2036-01-01T00:00:00Z]

It shows that the data objects are unchanged since the time the TSA states, as attested by the trust anchor you supply. From 0.7.0 it reads renewed records (RFC 4998 section 5): a later timestamp over an earlier one, or a new chain under a newer hash algorithm. Each timestamp must have been covered by the next before its certificate expired, and the newest must be valid at the verification time; a renewal that came too late is TSA_EXPIRED, and a broken link is EVIDENCE_MISMATCH. From 0.8.0 records are read exactly as Bouncy Castle's independent RFC 4998 implementation reads them (org.bouncycastle.tsp.ers 1.86, cross-checked 2026-10-08), and each record names the hash-tree convention it was built with. It checks no revocation (it is offline), and it says nothing about whether the content is true.

Note what code 3 does not mean: the verifier stops at the first failed check, so SCHEMA_INVALID means it never got as far as the signature. It is not a statement that the signature was fine.

Two failure modes are deliberately not distinguished. A wrong key and a mutated byte are cryptographically identical from the outside; code 8 is reported only when the signature bundle positively names a different signer, and otherwise the honest answer is code 7. This verifier does not upgrade an ambiguous failure into a more specific accusation.

Machine-readable output

certanix-verify verify evidence-pack.json --key cosign.pub --json
{
  "verified": false,
  "status": "SIGNATURE_MISMATCH",
  "exit_code": 7,
  "schema_version": "1.7",
  "detail": "recomputed canonical bytes do not match the signed digest",
  "verifier_version": "certanix-verify 0.3.0"
}

exit_code always equals the process exit code. verified is carried explicitly so a consumer never has to know that zero means success.

Two modes, deliberately different

Pack mode (the default) takes the pack JSON and recomputes its canonical form. A pack that has been re-serialised somewhere in your toolchain — different indentation, different key order, same content — still verifies. The signature binds the content, not the transport encoding, and reporting a benign JSON round-trip as tampering would be a false accusation.

Byte-exact mode takes a canonical-bytes file and its detached bundle:

certanix-verify verify evidence-pack.canonical.json --bundle evidence-pack.bundle --key cosign.pub

Here nothing is recomputed, so any byte change fails — including a re-serialisation that pack mode accepts. That is the correct behaviour for an archived artifact whose exact bytes are the claim. The two modes disagreeing on that one input is by design.

Standalone mode takes a signed artifact that is not a pack and names its own type in artifact_type: a delta report or delta refusal, self-evidence, or an EU Control and Origin Attestation (attestation):

certanix-verify verify attestation.json --standalone --key cosign.pub

The checks are the same as for a pack (structure, then the signature over the canonical bytes recomputed from the document as presented), against that type's bundled schema. An unknown or missing artifact_type is refused as an unsupported schema, never guessed.

Provenance

VENDORED.json records where this verifier came from: the platform source file and its SHA-256, the platform commit, and the schema version the bundled descriptors were taken from. The verification logic here is generated verbatim from the platform's single source — it is a copy, never a reimplementation — and the platform's CI asserts that this copy and the platform agree on every case in the verification conformance corpus.

Licence

BSD-3-Clause-Clear: see LICENSE. Who holds the copyright, and the assignment to come: see NOTICE. Patents: see PATENTS-NOTICE.md; the licence itself grants no patent rights.

Metadata

Release files for certanix-verify 0.14.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for certanix-verify 0.14.0
File Size Uploaded Provenance
certanix_verify-0.14.0.tar.gz 43.4 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for certanix-verify 0.14.0
File Interpreter ABI Platform
certanix_verify-0.14.0-py3-none-any.whl Python 3 none any Details

Total release size: 87.6 kB

Release files / certanix_verify-0.14.0.tar.gz

Download URL certanix_verify-0.14.0.tar.gz
Size 43.4 kB
Tags Source
SHA-256 checksum
How to use checksums
77f8940f35df8a746e6c783456998267c1d3116b8788aeb9d23ac0d1f9a8531b
BLAKE2b-256 checksum
How to use checksums
e9063886d79f7d0545c7f08c1bc6e0e3bae9c2a181614716b86711bf327e2b9f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release files / certanix_verify-0.14.0-py3-none-any.whl

Download URL certanix_verify-0.14.0-py3-none-any.whl
Size 44.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2aabf5b4a8a8dc5265b5ed85bb46387e2fee48c8419ed5f77288268de4e7797f
BLAKE2b-256 checksum
How to use checksums
b8baaaef3527afea85fca2c3993fedf62ad886f24ea213070cb24470e8834352
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Security for certanix-verify 0.14.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for certanix_verify-0.14.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.14.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page