Offline verifier CLI
The offline verifier is a small Python script shipped at
scripts/vy_verify.py. Point it at an audit bundle
ZIP and it will, without any database or network:
- Verify
manifest.sigagainstmanifest.jsonusing the embeddedpublic_key.pem. - Recompute the SHA-256 of every file listed in the manifest and compare to the stored values.
- Replay the full audit chain from
audit/chain.jsonland confirm the final record hash equals the manifest’s declaredchain_head.
Exit code 0 means the bundle is valid and untampered. Any other exit code is a failure.
Who runs it
Your external auditor, on their own laptop, against the ZIP you sent them. They do not need a Sukrit Nidhi login. They do not need access to your database. They do not need to trust your IT.
Prerequisites
- Python 3.10 or later (3.11+ recommended).
- The
cryptographyPython package. Apip install cryptographyis all that’s needed. - No other dependencies; the script is self-contained.
Usage
python scripts/vy_verify.py path/to/bdl_20260420_pune.zip
A successful run prints something like:
Verifying bdl_20260420_pune.zip…
Step 1 / 3 — signature
✓ manifest.sig verifies against public_key.pem
Step 2 / 3 — file hashes
✓ audit/chain.jsonl · sha256 5ffc2a1e…
✓ audit/chain_head.json · sha256 9afe0b33…
✓ exports/donations.csv · sha256 0b0c45d7…
✓ exports/expenses.csv · sha256 4c11de82…
…
Step 3 / 3 — chain replay
✓ replayed 1247 events · head b72e4c91…
Bundle is VALID.
On failure the script prints exactly which step failed, the file (if any) it was processing, and the mismatch details, then exits non-zero.
What a failure looks like
Step 2 / 3 — file hashes
× audit/chain.jsonl · expected 5ffc2a1e… got 7cbb33a0…
Bundle is INVALID. File hash mismatch.
This means the contents of chain.jsonl inside the
ZIP don’t match the hash recorded in the manifest. The ZIP has been
modified after signing, or the signing step itself was buggy. In either case
the auditor should ask for a freshly generated bundle.
What the verifier does not do
- It does not validate the business correctness of the numbers. That’s the auditor’s job.
- It does not check that the period chosen contains every event that happened. That’s why the bundle also ships the chain head — an auditor who wants to verify completeness cross-checks the head against a later anchor or a second bundle.
- It does not phone home. No network access is made at any point.