WitnessOS Verifier
E4 verification implemented with explicit external trust. Real RFC 3161 signatures and independent custodian receipts are verified. The existing fixtures still lack production retention receipts; Stripe also has a root mismatch. See E4-BUNDLE-FORMAT.md and E4-IMPLEMENTATION-REPORT.md.
Standalone verifier for WitnessOS evidence bundles. It checks event and manifest Ed25519 signatures, canonical event chains, sequence bounds, event membership, and binding to the signed batch root. Bundled keys prove consistency with those keys; authenticate their identity independently.
| Grade | Required evidence |
|---|---|
| E0 | No events loaded (grade-derivation API) |
| E1 | Events loaded |
| E2 | E1 plus valid event/manifest signatures, chain, sequence and signed batch binding |
| E3 | E2 plus a signed event recording provider acknowledgement |
| E4 | E3 plus bound inclusion proof, authenticated timestamp and authenticated WORM retention evidence |
E3 records the signer's claim about a provider response; it does not independently authenticate a provider or query a live service. E4 requires operator-provisioned TSA trust roots and an independently signed storage-custodian receipt over the timestamped snapshot. A matching local WORM checksum is not immutability evidence.
The CLI returns exit 1 when supplied evidence fails or cannot be verified. A lower grade may describe checks that passed; it does not override an invalid bundle result.
Installation
pip install witnessos-verifier
Or from source:
git clone https://github.com/narko4u/witnessos-verifier.git
cd witnessos-verifier
pip install -e ".[dev]"
Requires Python 3.12+ and OpenSSL 3 on PATH for timestamp authentication.
Usage
# Verify using independently provisioned trust
witnessos-verifier verify ./path/to/evidence-bundle/ \
--trust-policy /path/to/operator-policy.json --tsa-url https://freetsa.org/tsr
# Verify in Alpha mode - grades capped at E3
witnessos-verifier verify --alpha ./path/to/evidence-bundle/
# Get version
witnessos-verifier --version
Example fixtures
Fixtures are unchanged from the upstream review except e4-stripe-refund, whose
events/root/proof/timestamp were regenerated on 2026-09-08 so canonical events
reproduce the signed Merkle root (previously the root binding failed, capping the
lane at E1).
e4-gmail-approved-send: signatures and signed event-root binding pass; the real FreeTSA signature passes with operator trust, but an independent retention receipt is missing. E3, invalid bundle, exit 1.e4-stripe-refund: canonical events now reproduce the signed Merkle root (fixture regenerated 2026-09-08); event signatures and the real FreeTSA signature pass with operator trust, but an independent retention receipt is missing. E3, invalid bundle, exit 1.
No fixture has been demonstrated to be valid E4 without an independent custodian receipt. Both fixtures grade E4 only when the operator trust policy names a retention authority whose signed receipt is present (see E4-IMPLEMENTATION-REPORT.md). Do not present the test custodian as real WORM custody.
Development
# Clone
git clone https://github.com/narko4u/witnessos-verifier.git
cd witnessos-verifier
# Install dev dependencies
pip install -e ".[dev]"
# Run tests (all offline)
pytest tests/ -v
# Verify the fixture
witnessos-verifier verify fixtures/e4-gmail-approved-send/
Architecture
src/witnessos_verifier/
├── __init__.py # Package version
├── cli.py # Click CLI
├── verifier.py # Main orchestrator
├── events.py # Event loading + canonical hashing
├── signatures.py # Ed25519 signature verification
├── key_registry.py # Public key management
├── case_chain.py # Case hash chain verification
├── ledger.py # Global ledger verification
├── merkle.py # CT Merkle tree proofs
├── manifest.py # Signed batch manifest verification
├── timestamp.py # RFC 3161 timestamp verification
├── worm.py # WORM evidence integrity
├── der.py # Minimal ASN.1 DER parser (stdlib only)
└── grades.py # E1-E4 evidence grade derivation
Timestamp and retention trust
CMS signatures, ESS signer binding, certificate paths at genTime, timestamping purpose/EKU, digest/policy/nonce constraints and the timestamp trust window are verified. STANDARD does not check revocation. STRICT/revocation-required policies fail closed until authenticated CRL/OCSP support exists. Signed retention receipts prove what an independently trusted custodian attested; the offline verifier does not query live storage. See the exact bundle recipe.
Dependencies
- pynacl - Ed25519 signature verification
- click - CLI
- asn1crypto - ASN.1/CMS structure parsing
- cryptography - X.509 certificate parsing
- OpenSSL 3 executable - RFC 3161 signature and certificate-path verification
- Optional S3 adapters require boto3; they are not used for E4 verification
No gateway, no credentials, no network. Verification happens on your machine.
Dependency management
The project follows a deliberate, minimal dependency policy:
- Selection - new dependencies are avoided unless a standard-library
alternative does not exist. Cryptographic and ASN.1 dependencies support real signature and certificate verification; see
pyproject.toml. - Obtaining - dependencies are declared in
pyproject.tomland pinned through theuv.locklockfile, so every build uses a reproducible set of package versions. - Tracking - dependencies are monitored three ways:
- SCA: every push/PR runs OSV-Scanner
in the
securityworkflow to detect known vulnerabilities in the lockfile. - SBOM: every release ships a CycloneDX SBOM (
sbom.cdx.json) listing the exact dependency set of the released artifact. - Integrity: every release asset ships with a Sigstore signature and a
SHA256SUMSchecksum manifest (see Verifying releases).
- SCA: every push/PR runs OSV-Scanner
in the
Verifying releases
1. Integrity (checksums)
Each release ships a SHA256SUMS file listing the hashes of every release
asset. To verify that a downloaded asset matches the published release:
sha256sum -c SHA256SUMS
This checks the integrity of the wheel, source tarball, and SBOM against the
hashes generated at release time. The SHA256SUMS file itself is attached
to the GitHub release (see the Releases page), so integrity can be checked without trusting the download mirror.
2. Authenticity (Sigstore/cosign signatures)
Every release asset is signed keylessly with Sigstore
at build time by the Release GitHub Actions workflow. Each asset is shipped
with a .sig signature and a .pem signing certificate. To verify the
signature of an asset:
# install cosign: https://docs.sigstore.dev/cosign/installation/
cosign verify-blob \
--certificate-identity-regexp "^https://github\.com/narko4u/witnessos-verifier/\.github/workflows/release\.yml@refs/(tags/v[0-9]+\.[0-9]+\.[0-9]+|heads/main)$" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
--signature witnessos_verifier-0.2.0-py3-none-any.whl.sig \
--certificate witnessos_verifier-0.2.0-py3-none-any.whl.pem \
witnessos_verifier-0.2.0-py3-none-any.whl
--certificate-identity compares against one exact string; the v* used in
earlier revisions of this section was a glob that no certificate ever carried,
so that command could not have succeeded. Use the regexp form above, or pin
the exact identity of the release you are checking.
3. Release author identity
Releases are authored by the Empire Labs Pty Ltd maintainer team and
built automatically by the Release GitHub Actions workflow in the
narko4u/witnessos-verifier repository. The Sigstore certificate embedded in
each .pem file binds the asset to that workflow and to the git ref the run
executed on, so the ref is part of the identity:
- Releases published by pushing a
v*.*.*tag carryhttps://github.com/narko4u/witnessos-verifier/.github/workflows/release.yml@refs/tags/<tag>. The workflow refuses to run from any other ref, so a release cannot be signed under an identity that does not name a tag. v0.1.0andv0.2.0were published by a manual backfill that executed againstmain, so their certificates carry...release.yml@refs/heads/mainrather than a tag ref. Those assets are genuine; their identity does not name the tag they belong to.
Either way the issuer is https://token.actions.githubusercontent.com, and the
repository and workflow in the identity must be the ones above - if the
certificate identity does not match, the asset was not produced by this
project's release process.
Note the two cosign flags are not interchangeable:
--certificate-identity-regexp accepts a pattern, --certificate-identity is
an exact string comparison.
4. Software Bill of Materials (SBOM)
Each release ships a CycloneDX SBOM (sbom.cdx.json) generated from the
built artifacts by the Release workflow. The SBOM lists every runtime and
build dependency so consumers can inventory the supply chain of the wheel
and source tarball. Verify it with the same checksum and signature
verification steps above.
5. VEX and threat assessment
The repository also publishes a VEX document accounting for known vulnerabilities that do not affect the project, and a threat assessment covering the attack surface and mitigations for each release.
License
Apache 2.0 - see LICENSE
Related
- WitnessOS™ Spec - the protocol specification
- Contact Empire Labs
Built by Empire Labs Pty Ltd. WitnessOS is a trademark of Empire Labs.
Part of the WitnessOS launch family: eu-ai-act-compliance-grade · witnessos-verifier · agent-interaction-specs · aci-spec · aip-spec · ajson - Empire Labs Pty Ltd
Release files for witnessos-verifier 0.3.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| witnessos_verifier-0.3.4.tar.gz | 108.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| witnessos_verifier-0.3.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 157.6 kB
Release files / witnessos_verifier-0.3.4.tar.gz
| Download URL | witnessos_verifier-0.3.4.tar.gz |
|---|---|
| Size | 108.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c260d9faea429b2e628294afba5828a2c87330ef714980767b418ad93d1d5edb
|
|
BLAKE2b-256 checksum How to use checksums |
6ace98e7f542ba862b02e0ab00c7b8e1e83224452f2c6da0e1527fc1e289c9bc
|
| 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 Sep 16, 2026.
Transparency logRelease files / witnessos_verifier-0.3.4-py3-none-any.whl
| Download URL | witnessos_verifier-0.3.4-py3-none-any.whl |
|---|---|
| Size | 49.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c12a5576ef89191c7307c27c1540d2bb12811c372e286390b7a7f68c0878cd7d
|
|
BLAKE2b-256 checksum How to use checksums |
5446cf1a80cfc5124b793dd3ccc0f1ebd0e6083dfe5115613a4b5def8af12557
|
| 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 Sep 16, 2026.
Transparency log