Evidence verification

Verify an evidence package

Confirm that a Behavry evidence package is exactly what was signed, and that no event was altered, removed, or reordered. No account, no tenant access, no database.

Nothing you submit is stored. The package is verified in memory and discarded. It is never logged or forwarded.

The .zip exported from a Behavry APR, or an agent's authority package.

Drop the .zip here, or choose a file

The issuing tenant's behavry-trust-anchor.json. Supplying it is what makes the result independent of Behavry. See why this matters.

Public key files of independent observers, such as the Minotaur key ({"kid", "public_key_hex", "observer_id", "observer_type"}). Choose one or more. Observations and assessment bundles signed by a key you do not supply are reported as not independently verified.

A PEM bundle of the timestamp authorities you trust, for the audit anchors an authority package carries. Without it the TSA certificate chain is reported as not validated.

The tenant's newest anchor, obtained from Behavry independently of the package (/api/v1/audit/anchors/head). Choose one or more. Every provenance entry older than a head must be anchored in the package, which rules out dropping the newest anchors. Without one, that truncation cannot be ruled out. A head may be a .json record or a gzipped .json.gz object straight from the WORM bucket.

Verify an audit anchor

An audit anchor is the RFC 3161 proof of when: a third-party timestamp over a digest that commits to a tenant's audit events and agent provenance for one period.

The JSON exported from /api/v1/audit/anchors/{id}/export.

The issuing tenant's behavry-trust-anchor.json.

A PEM bundle of the timestamp authorities you trust.

What the result is worth

Verification is only as good as the key it checks against. There are three ways to supply one and they are not equally strong. Every report says which one it used.

You supply the tenant's trust anchor strongest
The package was signed by the key the tenant handed you out-of-band. Behavry is not in the loop.
The published registry convenience only
If you supply no anchor, we look the signing key up in our published registry. That confirms the package is internally consistent and signed by the named key, but the key came from Behavry. This is Behavry vouching for Behavry. If the result matters, get the anchor from the issuing tenant.

An evidence package does not contain the key needed to verify it. It carries only a truncated fingerprint, so you can confirm you are holding the right anchor.

Verify offline instead

The same checks, on your own machine, with no network and one dependency. This is the air-gapped path, and it is the one to use when the package is sensitive enough that you would rather not hand it to anyone at all.

pipx install behavry-verify

behavry-verify --package apr-APR-2026-001942.zip \
               --trust-anchor behavry-trust-anchor.json

behavry-verify --package authority-<agent_id>.zip \
               --trust-anchor behavry-trust-anchor.json \
               --observer-anchor minotaur-observer-key.json \
               --tsa-roots your-tsa-roots.pem \
               --anchor-head anchor-head.json

behavry-verify --audit-anchor behavry-anchor.json \
               --trust-anchor behavry-trust-anchor.json

Exit codes are 0 verified, 1 not verified, 2 unusable input, so it drops straight into CI.