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.1.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.1-py3-none-any.whl (23.7 kB view details)

Uploaded Python 3

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

Hashes for trustflash_verify-0.4.1.tar.gz
Algorithm Hash digest
SHA256 bff3c926eb62911cf14fc6c8365183cbd1ad9749a03899791d19468b431090af
MD5 39a99eaa99910b1d886998c814c25797
BLAKE2b-256 1c18eb1c6f7154c66a70f12112f00cdc0c81725137791f390a146e39b0e7909b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for trustflash_verify-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 df09e93a86e1deb3f81854ee1e6890d550a9871838d532986904dc8204b01418
MD5 2899ae453344db668d1f804e5fa5a5bf
BLAKE2b-256 accd251d388c7b2ea5ae8e315cd910c0e6763479f2518a8986a6827f3f3b057b

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.4.1 This release

2 files

0.4.0

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