Metadata-Version: 2.4
Name: trustflash-verify
Version: 0.4.1
Summary: Open-source forensic verifier for TrustSHIELD/AIREC TrustFlash audit-export bundles. Verifies Ed25519 checkpoint signatures, the SHA-256 event hash chain, checkpoint-to-event binding, and the signed Forensic Confidence score offline, no platform access required.
Home-page: https://airecai.com
Author: Northgate Strategic LLC
Author-email: support@northgatestrategic.com
License: MIT
Keywords: audit forensic verification ed25519 sha256 ai-governance trustshield
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: Legal Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: System :: Logging
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cryptography>=41.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# 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

```bash
pip install cryptography
```

Then either:

```bash
# 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

```bash
# 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)
```
