trustflash-verify
Open-source forensic verifier for TrustSHIELD/AIREC TrustFlash export bundles (PF21 patent — TrustFlash Behavioral Audit Black Box).
Why this exists
Auditors don't trust "we have a database with hash columns." They want cryptographic evidence they can verify themselves, offline, without access to the platform's infrastructure.
A TrustFlash forensic export bundle is a single JSON file containing:
- The platform's Ed25519 public key (PEM-encoded)
- Recent Ed25519-signed checkpoints over the audit chain head
- Recent enforcement events with their per-event hash chain
- Step-by-step verification instructions
This tool independently verifies that bundle. It depends only on
the cryptography library (the same one Python's TLS stack uses); the
verifier itself is a single Python file you can read, audit, fork, or
re-implement in any language.
Installation
pip install cryptography
Then either:
# Run directly:
python trustflash_verify.py /path/to/bundle.json
# Or symlink onto your PATH:
chmod +x trustflash_verify.py
ln -s "$(pwd)/trustflash_verify.py" ~/.local/bin/trustflash-verify
trustflash-verify /path/to/bundle.json
Usage
# Verify a bundle, human-readable summary
trustflash-verify bundle.json
# JSON output for tooling
trustflash-verify bundle.json --json
# Use a separately-trusted public key (e.g., one Northgate Strategic
# published on a different channel) instead of the key embedded in
# the bundle. This is the strongest guarantee: it proves the bundle
# was signed by the entity whose key fingerprint you trust, even if
# the bundle itself was tampered to swap keys.
trustflash-verify bundle.json --public-key /path/to/key.pem
What the tool checks
For each checkpoint in the bundle:
- Select the verification key by the checkpoint's
key_idfrom the bundle'spublic_keysarray — a bundle that spans a key rotation carries every key it was signed under. Falls back to the top-levelpublic_key_pemfor checkpoints with nokey_idor an unlisted one (and for older single-key bundles that predatepublic_keys). - Recompute canonical signed bytes:
trustflash/v1|<tenant_id>|<chain_head_hash>|<event_count>|<checkpoint_at>|<prev_checkpoint_id_or_GENESIS> - Verify Ed25519 signature against the selected public key.
- Report
valid/signature mismatch/decode error.
For each event in the bundle:
- Recompute canonical hash input from row fields:
<id>|<tenant_id>|<user_id>|<module_name>|<decision>|<action>|<severity>|<trust_score>|<violation_type>|<endpoint>|<request_id>|<timestamp>|<prev_event_hash> - Compute
SHA256of that canonical input. - Compare against the row's stored
event_hash. - Verify
prev_event_hashlinks to the previous event'sevent_hash(orGENESISfor the first event).
Checkpoint→event binding (tool v0.4.0):
A valid signature proves a checkpoint record was signed; a self-consistent
event chain proves internal linkage. Neither alone proves the signer signed
these events. For every checkpoint whose event_count falls inside the
exported slice, the event at that chain_position must carry
event_hash == chain_head_hash. A mismatch is a hard failure (exit 6) —
the events were rebuilt, or the checkpoint belongs to a different chain. A
signed position with no event in the slice is reported as a warning (not a
failure): historical write-race forks and export-slice boundaries produce
that shape on healthy data, and the server-side full-chain verifier is the
authority there.
Forensic Confidence recompute (tool v0.4.0):
If the bundle carries a forensic_confidence block, the platform's 0-100 /
A-F Forensic Confidence score is recomputable offline from the bundle
alone. The tool:
- Verifies the Ed25519 signature over the exact bytes of
payload_canonical(key selected bykey_id, same registry as checkpoints;--public-keypins it). - Requires the human-readable
payloadcopy to equal the signed copy. - Requires the attestation's
chain_head_hashto equal the event hash of the highest-chain_positionevent in the bundle — the attestation is bound to this chain and cannot be replayed against rebuilt events. - Recomputes all five component scores from the attested integer inputs
(chain continuity, signature validity, override anomaly rate, reflex
distribution, egress balance), the weighted composite, and the letter
grade, and compares them to the attested values. A component with a
zero denominator is a disclosed vacuous pass ("no data in window",
insufficient_data: true) — an undisclosed one is a failure.
Every attested value is an aggregate: integer counts, scores, weights, a grade, a window length, a timestamp, and hashes already present in the bundle. No user identifier, email, or content fragment appears in the attestation. A bundle without the block predates the feature and is reported as "score recompute not available" — never as a failure.
Exit codes
| Code | Meaning |
|---|---|
| 0 | All checkpoints + events verified clean |
| 1 | One or more checkpoint signatures invalid |
| 2 | One or more events have broken hash chain |
| 3 | Bundle file or schema error |
| 4 | cryptography import error |
| 5 | Bundle cannot be hash-verified (see below) — not a tamper finding |
| 6 | Checkpoint→event binding mismatch — the signer did not sign these events |
| 7 | Forensic Confidence attestation invalid, or the score does not recompute |
Exit 5 — UNVERIFIABLE
A bundle exported before canonical v1 omits four of the thirteen fields the
database hashes (user_id, violation_type, endpoint, request_id) and
re-renders the timestamp in a different format, so event hashes cannot be
recomputed from it. The tool reports that as its own verdict rather than
calling the data tampered, because a false tamper alarm on healthy data is
worse than no answer — it teaches operators to disregard real alarms.
Chain linkage is still fully verified on these bundles, and a genuine
linkage break still returns exit 2. To verify hashes, re-export from a
server running canonical v1 ("canonical_version": 1 appears at the top
level of the bundle JSON).
If you are scripting this tool, treat 0 as pass, 5 as "inconclusive, get a better export", and 1/2/6/7 as findings.
Trust model
The tool's verification is sound iff:
- The
cryptographylibrary is honest about Ed25519 verification. This is the same library Python's TLS stack uses; it's reviewed by NIST and widely audited. - The bundle's public key is what the bundle claims it is. If a
relying party wants stronger assurance of the public-key provenance,
they compare its fingerprint against a key fingerprint published by
Northgate Strategic out-of-band, then run with
--public-key.
The tool itself is a single Python file you can read in 10 minutes. There is no hidden network call, no telemetry, no callback to Northgate Strategic. Bundle in → verdict out.
License
MIT — anyone can audit, modify, or redistribute. The verifier is the trust anchor; the platform's trustworthiness depends on this tool being independently scrutinizable.
Sample output
trustflash-verify v0.4.0
schema: trustflash/v1
tenant: northgate-strategic
key fp: 3ecb62b07e0b0984
✓ Checkpoints: 12/12 valid
[ok] cp_a846e749 — ok
[ok] cp_b912f3e2 — ok
...
✓ Events: 2612/2612 valid
All events verified.
✓ Checkpoint→event binding: 12/12 checkpoints bound to exported events
✓ Forensic Confidence: attested 91.3 (A-) — recomputed 91.3 (A-) from the signed signal inputs
Verdict: CLEAN (exit code 0)
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file trustflash_verify-0.4.1.tar.gz.
File metadata
- Download URL: trustflash_verify-0.4.1.tar.gz
- Upload date:
- Size: 34.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bff3c926eb62911cf14fc6c8365183cbd1ad9749a03899791d19468b431090af
|
|
| MD5 |
39a99eaa99910b1d886998c814c25797
|
|
| BLAKE2b-256 |
1c18eb1c6f7154c66a70f12112f00cdc0c81725137791f390a146e39b0e7909b
|
File details
Details for the file trustflash_verify-0.4.1-py3-none-any.whl.
File metadata
- Download URL: trustflash_verify-0.4.1-py3-none-any.whl
- Upload date:
- Size: 23.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df09e93a86e1deb3f81854ee1e6890d550a9871838d532986904dc8204b01418
|
|
| MD5 |
2899ae453344db668d1f804e5fa5a5bf
|
|
| BLAKE2b-256 |
accd251d388c7b2ea5ae8e315cd910c0e6763479f2518a8986a6827f3f3b057b
|