Skip to main content

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:

  1. Select the verification key by the checkpoint's key_id from the bundle's public_keys array — a bundle that spans a key rotation carries every key it was signed under. Falls back to the top-level public_key_pem for checkpoints with no key_id or an unlisted one (and for older single-key bundles that predate public_keys).
  2. Recompute canonical signed bytes: trustflash/v1|<tenant_id>|<chain_head_hash>|<event_count>|<checkpoint_at>|<prev_checkpoint_id_or_GENESIS>
  3. Verify Ed25519 signature against the selected public key.
  4. Report valid / signature mismatch / decode error.

For each event in the bundle:

  1. 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>
  2. Compute SHA256 of that canonical input.
  3. Compare against the row's stored event_hash.
  4. Verify prev_event_hash links to the previous event's event_hash (or GENESIS for 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:

  1. Verifies the Ed25519 signature over the exact bytes of payload_canonical (key selected by key_id, same registry as checkpoints; --public-key pins it).
  2. Requires the human-readable payload copy to equal the signed copy.
  3. Requires the attestation's chain_head_hash to equal the event hash of the highest-chain_position event in the bundle — the attestation is bound to this chain and cannot be replayed against rebuilt events.
  4. 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 cryptography library 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

trustflash_verify-0.4.0.tar.gz (34.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

trustflash_verify-0.4.0-py3-none-any.whl (23.7 kB view details)

Uploaded Python 3

File details

Details for the file trustflash_verify-0.4.0.tar.gz.

File metadata

  • Download URL: trustflash_verify-0.4.0.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

Hashes for trustflash_verify-0.4.0.tar.gz
Algorithm Hash digest
SHA256 22b64c9a09172959b8fac0ef1dfe92c8b049308f7ee21f990d4c16a76612314f
MD5 7f357fffb86d06311f96dc3049fef914
BLAKE2b-256 50226d6d9d163120e387af7e2351a7a85df08c5043ff4f2d9041d38ba9b7d07f

See more details on using hashes here.

File details

Details for the file trustflash_verify-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for trustflash_verify-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6346053c921265f033da24fcfa8cc4cab813124cc5012ba23f4598cfaffd8ca3
MD5 c22fbce07007c5e7c2a88109f99b0a2b
BLAKE2b-256 789a5ec2099d1995ea080658b736e5265901edf35c58f1af599166deb0865eab

See more details on using hashes here.

Release history Release notifications | RSS feed

0.4.1

2 files

This release

0.4.0 This release

2 files

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