trustflash-verify 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Northgate Strategic LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a
6
+ copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included
14
+ in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,234 @@
1
+ Metadata-Version: 2.4
2
+ Name: trustflash-verify
3
+ Version: 0.4.0
4
+ 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.
5
+ Home-page: https://github.com/northgate-strategic/trustflash-verifier
6
+ Author: Northgate Strategic LLC
7
+ Author-email: support@northgatestrategic.com
8
+ License: MIT
9
+ Keywords: audit forensic verification ed25519 sha256 ai-governance trustshield
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Information Technology
12
+ Classifier: Intended Audience :: Legal Industry
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Security :: Cryptography
20
+ Classifier: Topic :: System :: Logging
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: cryptography>=41.0.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=7; extra == "dev"
27
+ Dynamic: author
28
+ Dynamic: author-email
29
+ Dynamic: classifier
30
+ Dynamic: description
31
+ Dynamic: description-content-type
32
+ Dynamic: home-page
33
+ Dynamic: keywords
34
+ Dynamic: license
35
+ Dynamic: license-file
36
+ Dynamic: provides-extra
37
+ Dynamic: requires-dist
38
+ Dynamic: requires-python
39
+ Dynamic: summary
40
+
41
+ # trustflash-verify
42
+
43
+ Open-source forensic verifier for TrustSHIELD/AIREC TrustFlash export
44
+ bundles (PF21 patent — TrustFlash Behavioral Audit Black Box).
45
+
46
+ ## Why this exists
47
+
48
+ Auditors don't trust "we have a database with hash columns." They want
49
+ **cryptographic evidence they can verify themselves, offline, without
50
+ access to the platform's infrastructure**.
51
+
52
+ A TrustFlash forensic export bundle is a single JSON file containing:
53
+
54
+ - The platform's Ed25519 public key (PEM-encoded)
55
+ - Recent Ed25519-signed checkpoints over the audit chain head
56
+ - Recent enforcement events with their per-event hash chain
57
+ - Step-by-step verification instructions
58
+
59
+ This tool **independently verifies** that bundle. It depends only on
60
+ the `cryptography` library (the same one Python's TLS stack uses); the
61
+ verifier itself is a single Python file you can read, audit, fork, or
62
+ re-implement in any language.
63
+
64
+ ## Installation
65
+
66
+ ```bash
67
+ pip install cryptography
68
+ ```
69
+
70
+ Then either:
71
+
72
+ ```bash
73
+ # Run directly:
74
+ python trustflash_verify.py /path/to/bundle.json
75
+
76
+ # Or symlink onto your PATH:
77
+ chmod +x trustflash_verify.py
78
+ ln -s "$(pwd)/trustflash_verify.py" ~/.local/bin/trustflash-verify
79
+ trustflash-verify /path/to/bundle.json
80
+ ```
81
+
82
+ ## Usage
83
+
84
+ ```bash
85
+ # Verify a bundle, human-readable summary
86
+ trustflash-verify bundle.json
87
+
88
+ # JSON output for tooling
89
+ trustflash-verify bundle.json --json
90
+
91
+ # Use a separately-trusted public key (e.g., one Northgate Strategic
92
+ # published on a different channel) instead of the key embedded in
93
+ # the bundle. This is the strongest guarantee: it proves the bundle
94
+ # was signed by the entity whose key fingerprint you trust, even if
95
+ # the bundle itself was tampered to swap keys.
96
+ trustflash-verify bundle.json --public-key /path/to/key.pem
97
+ ```
98
+
99
+ ## What the tool checks
100
+
101
+ For each **checkpoint** in the bundle:
102
+
103
+ 1. Select the verification key by the checkpoint's `key_id` from the
104
+ bundle's `public_keys` array — a bundle that spans a key rotation
105
+ carries every key it was signed under. Falls back to the top-level
106
+ `public_key_pem` for checkpoints with no `key_id` or an unlisted one
107
+ (and for older single-key bundles that predate `public_keys`).
108
+ 2. Recompute canonical signed bytes:
109
+ `trustflash/v1|<tenant_id>|<chain_head_hash>|<event_count>|<checkpoint_at>|<prev_checkpoint_id_or_GENESIS>`
110
+ 3. Verify Ed25519 signature against the selected public key.
111
+ 4. Report `valid` / `signature mismatch` / `decode error`.
112
+
113
+ For each **event** in the bundle:
114
+
115
+ 1. Recompute canonical hash input from row fields:
116
+ `<id>|<tenant_id>|<user_id>|<module_name>|<decision>|<action>|<severity>|<trust_score>|<violation_type>|<endpoint>|<request_id>|<timestamp>|<prev_event_hash>`
117
+ 2. Compute `SHA256` of that canonical input.
118
+ 3. Compare against the row's stored `event_hash`.
119
+ 4. Verify `prev_event_hash` links to the previous event's `event_hash`
120
+ (or `GENESIS` for the first event).
121
+
122
+ **Checkpoint→event binding** (tool v0.4.0):
123
+
124
+ A valid signature proves a checkpoint record was signed; a self-consistent
125
+ event chain proves internal linkage. Neither alone proves the signer signed
126
+ *these* events. For every checkpoint whose `event_count` falls inside the
127
+ exported slice, the event at that `chain_position` must carry
128
+ `event_hash == chain_head_hash`. A mismatch is a hard failure (exit 6) —
129
+ the events were rebuilt, or the checkpoint belongs to a different chain. A
130
+ signed position with no event in the slice is reported as a warning (not a
131
+ failure): historical write-race forks and export-slice boundaries produce
132
+ that shape on healthy data, and the server-side full-chain verifier is the
133
+ authority there.
134
+
135
+ **Forensic Confidence recompute** (tool v0.4.0):
136
+
137
+ If the bundle carries a `forensic_confidence` block, the platform's 0-100 /
138
+ A-F Forensic Confidence score is recomputable offline from the bundle
139
+ alone. The tool:
140
+
141
+ 1. Verifies the Ed25519 signature over the **exact** bytes of
142
+ `payload_canonical` (key selected by `key_id`, same registry as
143
+ checkpoints; `--public-key` pins it).
144
+ 2. Requires the human-readable `payload` copy to equal the signed copy.
145
+ 3. Requires the attestation's `chain_head_hash` to equal the event hash of
146
+ the highest-`chain_position` event in the bundle — the attestation is
147
+ bound to *this* chain and cannot be replayed against rebuilt events.
148
+ 4. Recomputes all five component scores from the attested integer inputs
149
+ (chain continuity, signature validity, override anomaly rate, reflex
150
+ distribution, egress balance), the weighted composite, and the letter
151
+ grade, and compares them to the attested values. A component with a
152
+ zero denominator is a *disclosed* vacuous pass ("no data in window",
153
+ `insufficient_data: true`) — an undisclosed one is a failure.
154
+
155
+ Every attested value is an aggregate: integer counts, scores, weights, a
156
+ grade, a window length, a timestamp, and hashes already present in the
157
+ bundle. No user identifier, email, or content fragment appears in the
158
+ attestation. A bundle **without** the block predates the feature and is
159
+ reported as "score recompute not available" — never as a failure.
160
+
161
+ ## Exit codes
162
+
163
+ | Code | Meaning |
164
+ |------|---------|
165
+ | 0 | All checkpoints + events verified clean |
166
+ | 1 | One or more checkpoint signatures invalid |
167
+ | 2 | One or more events have broken hash chain |
168
+ | 3 | Bundle file or schema error |
169
+ | 4 | cryptography import error |
170
+ | 5 | Bundle cannot be hash-verified (see below) — **not** a tamper finding |
171
+ | 6 | Checkpoint→event binding mismatch — the signer did not sign these events |
172
+ | 7 | Forensic Confidence attestation invalid, or the score does not recompute |
173
+
174
+ ### Exit 5 — UNVERIFIABLE
175
+
176
+ A bundle exported before canonical v1 omits four of the thirteen fields the
177
+ database hashes (`user_id`, `violation_type`, `endpoint`, `request_id`) and
178
+ re-renders the timestamp in a different format, so event hashes cannot be
179
+ recomputed from it. The tool reports that as its own verdict rather than
180
+ calling the data tampered, because a false tamper alarm on healthy data is
181
+ worse than no answer — it teaches operators to disregard real alarms.
182
+
183
+ Chain **linkage** is still fully verified on these bundles, and a genuine
184
+ linkage break still returns exit 2. To verify hashes, re-export from a
185
+ server running canonical v1 (`"canonical_version": 1` appears at the top
186
+ level of the bundle JSON).
187
+
188
+ If you are scripting this tool, treat 0 as pass, 5 as "inconclusive, get a
189
+ better export", and 1/2/6/7 as findings.
190
+
191
+ ## Trust model
192
+
193
+ The tool's verification is sound iff:
194
+
195
+ - The `cryptography` library is honest about Ed25519 verification.
196
+ This is the same library Python's TLS stack uses; it's reviewed by
197
+ NIST and widely audited.
198
+ - The bundle's public key is what the bundle claims it is. If a
199
+ relying party wants stronger assurance of the public-key provenance,
200
+ they compare its fingerprint against a key fingerprint published by
201
+ Northgate Strategic out-of-band, then run with `--public-key`.
202
+
203
+ The tool itself is a single Python file you can read in 10 minutes.
204
+ There is no hidden network call, no telemetry, no callback to
205
+ Northgate Strategic. Bundle in → verdict out.
206
+
207
+ ## License
208
+
209
+ MIT — anyone can audit, modify, or redistribute. The verifier is the
210
+ trust anchor; the platform's trustworthiness depends on this tool
211
+ being independently scrutinizable.
212
+
213
+ ## Sample output
214
+
215
+ ```
216
+ trustflash-verify v0.4.0
217
+ schema: trustflash/v1
218
+ tenant: northgate-strategic
219
+ key fp: 3ecb62b07e0b0984
220
+
221
+ ✓ Checkpoints: 12/12 valid
222
+ [ok] cp_a846e749 — ok
223
+ [ok] cp_b912f3e2 — ok
224
+ ...
225
+
226
+ ✓ Events: 2612/2612 valid
227
+ All events verified.
228
+
229
+ ✓ Checkpoint→event binding: 12/12 checkpoints bound to exported events
230
+
231
+ ✓ Forensic Confidence: attested 91.3 (A-) — recomputed 91.3 (A-) from the signed signal inputs
232
+
233
+ Verdict: CLEAN (exit code 0)
234
+ ```
@@ -0,0 +1,194 @@
1
+ # trustflash-verify
2
+
3
+ Open-source forensic verifier for TrustSHIELD/AIREC TrustFlash export
4
+ bundles (PF21 patent — TrustFlash Behavioral Audit Black Box).
5
+
6
+ ## Why this exists
7
+
8
+ Auditors don't trust "we have a database with hash columns." They want
9
+ **cryptographic evidence they can verify themselves, offline, without
10
+ access to the platform's infrastructure**.
11
+
12
+ A TrustFlash forensic export bundle is a single JSON file containing:
13
+
14
+ - The platform's Ed25519 public key (PEM-encoded)
15
+ - Recent Ed25519-signed checkpoints over the audit chain head
16
+ - Recent enforcement events with their per-event hash chain
17
+ - Step-by-step verification instructions
18
+
19
+ This tool **independently verifies** that bundle. It depends only on
20
+ the `cryptography` library (the same one Python's TLS stack uses); the
21
+ verifier itself is a single Python file you can read, audit, fork, or
22
+ re-implement in any language.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install cryptography
28
+ ```
29
+
30
+ Then either:
31
+
32
+ ```bash
33
+ # Run directly:
34
+ python trustflash_verify.py /path/to/bundle.json
35
+
36
+ # Or symlink onto your PATH:
37
+ chmod +x trustflash_verify.py
38
+ ln -s "$(pwd)/trustflash_verify.py" ~/.local/bin/trustflash-verify
39
+ trustflash-verify /path/to/bundle.json
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ```bash
45
+ # Verify a bundle, human-readable summary
46
+ trustflash-verify bundle.json
47
+
48
+ # JSON output for tooling
49
+ trustflash-verify bundle.json --json
50
+
51
+ # Use a separately-trusted public key (e.g., one Northgate Strategic
52
+ # published on a different channel) instead of the key embedded in
53
+ # the bundle. This is the strongest guarantee: it proves the bundle
54
+ # was signed by the entity whose key fingerprint you trust, even if
55
+ # the bundle itself was tampered to swap keys.
56
+ trustflash-verify bundle.json --public-key /path/to/key.pem
57
+ ```
58
+
59
+ ## What the tool checks
60
+
61
+ For each **checkpoint** in the bundle:
62
+
63
+ 1. Select the verification key by the checkpoint's `key_id` from the
64
+ bundle's `public_keys` array — a bundle that spans a key rotation
65
+ carries every key it was signed under. Falls back to the top-level
66
+ `public_key_pem` for checkpoints with no `key_id` or an unlisted one
67
+ (and for older single-key bundles that predate `public_keys`).
68
+ 2. Recompute canonical signed bytes:
69
+ `trustflash/v1|<tenant_id>|<chain_head_hash>|<event_count>|<checkpoint_at>|<prev_checkpoint_id_or_GENESIS>`
70
+ 3. Verify Ed25519 signature against the selected public key.
71
+ 4. Report `valid` / `signature mismatch` / `decode error`.
72
+
73
+ For each **event** in the bundle:
74
+
75
+ 1. Recompute canonical hash input from row fields:
76
+ `<id>|<tenant_id>|<user_id>|<module_name>|<decision>|<action>|<severity>|<trust_score>|<violation_type>|<endpoint>|<request_id>|<timestamp>|<prev_event_hash>`
77
+ 2. Compute `SHA256` of that canonical input.
78
+ 3. Compare against the row's stored `event_hash`.
79
+ 4. Verify `prev_event_hash` links to the previous event's `event_hash`
80
+ (or `GENESIS` for the first event).
81
+
82
+ **Checkpoint→event binding** (tool v0.4.0):
83
+
84
+ A valid signature proves a checkpoint record was signed; a self-consistent
85
+ event chain proves internal linkage. Neither alone proves the signer signed
86
+ *these* events. For every checkpoint whose `event_count` falls inside the
87
+ exported slice, the event at that `chain_position` must carry
88
+ `event_hash == chain_head_hash`. A mismatch is a hard failure (exit 6) —
89
+ the events were rebuilt, or the checkpoint belongs to a different chain. A
90
+ signed position with no event in the slice is reported as a warning (not a
91
+ failure): historical write-race forks and export-slice boundaries produce
92
+ that shape on healthy data, and the server-side full-chain verifier is the
93
+ authority there.
94
+
95
+ **Forensic Confidence recompute** (tool v0.4.0):
96
+
97
+ If the bundle carries a `forensic_confidence` block, the platform's 0-100 /
98
+ A-F Forensic Confidence score is recomputable offline from the bundle
99
+ alone. The tool:
100
+
101
+ 1. Verifies the Ed25519 signature over the **exact** bytes of
102
+ `payload_canonical` (key selected by `key_id`, same registry as
103
+ checkpoints; `--public-key` pins it).
104
+ 2. Requires the human-readable `payload` copy to equal the signed copy.
105
+ 3. Requires the attestation's `chain_head_hash` to equal the event hash of
106
+ the highest-`chain_position` event in the bundle — the attestation is
107
+ bound to *this* chain and cannot be replayed against rebuilt events.
108
+ 4. Recomputes all five component scores from the attested integer inputs
109
+ (chain continuity, signature validity, override anomaly rate, reflex
110
+ distribution, egress balance), the weighted composite, and the letter
111
+ grade, and compares them to the attested values. A component with a
112
+ zero denominator is a *disclosed* vacuous pass ("no data in window",
113
+ `insufficient_data: true`) — an undisclosed one is a failure.
114
+
115
+ Every attested value is an aggregate: integer counts, scores, weights, a
116
+ grade, a window length, a timestamp, and hashes already present in the
117
+ bundle. No user identifier, email, or content fragment appears in the
118
+ attestation. A bundle **without** the block predates the feature and is
119
+ reported as "score recompute not available" — never as a failure.
120
+
121
+ ## Exit codes
122
+
123
+ | Code | Meaning |
124
+ |------|---------|
125
+ | 0 | All checkpoints + events verified clean |
126
+ | 1 | One or more checkpoint signatures invalid |
127
+ | 2 | One or more events have broken hash chain |
128
+ | 3 | Bundle file or schema error |
129
+ | 4 | cryptography import error |
130
+ | 5 | Bundle cannot be hash-verified (see below) — **not** a tamper finding |
131
+ | 6 | Checkpoint→event binding mismatch — the signer did not sign these events |
132
+ | 7 | Forensic Confidence attestation invalid, or the score does not recompute |
133
+
134
+ ### Exit 5 — UNVERIFIABLE
135
+
136
+ A bundle exported before canonical v1 omits four of the thirteen fields the
137
+ database hashes (`user_id`, `violation_type`, `endpoint`, `request_id`) and
138
+ re-renders the timestamp in a different format, so event hashes cannot be
139
+ recomputed from it. The tool reports that as its own verdict rather than
140
+ calling the data tampered, because a false tamper alarm on healthy data is
141
+ worse than no answer — it teaches operators to disregard real alarms.
142
+
143
+ Chain **linkage** is still fully verified on these bundles, and a genuine
144
+ linkage break still returns exit 2. To verify hashes, re-export from a
145
+ server running canonical v1 (`"canonical_version": 1` appears at the top
146
+ level of the bundle JSON).
147
+
148
+ If you are scripting this tool, treat 0 as pass, 5 as "inconclusive, get a
149
+ better export", and 1/2/6/7 as findings.
150
+
151
+ ## Trust model
152
+
153
+ The tool's verification is sound iff:
154
+
155
+ - The `cryptography` library is honest about Ed25519 verification.
156
+ This is the same library Python's TLS stack uses; it's reviewed by
157
+ NIST and widely audited.
158
+ - The bundle's public key is what the bundle claims it is. If a
159
+ relying party wants stronger assurance of the public-key provenance,
160
+ they compare its fingerprint against a key fingerprint published by
161
+ Northgate Strategic out-of-band, then run with `--public-key`.
162
+
163
+ The tool itself is a single Python file you can read in 10 minutes.
164
+ There is no hidden network call, no telemetry, no callback to
165
+ Northgate Strategic. Bundle in → verdict out.
166
+
167
+ ## License
168
+
169
+ MIT — anyone can audit, modify, or redistribute. The verifier is the
170
+ trust anchor; the platform's trustworthiness depends on this tool
171
+ being independently scrutinizable.
172
+
173
+ ## Sample output
174
+
175
+ ```
176
+ trustflash-verify v0.4.0
177
+ schema: trustflash/v1
178
+ tenant: northgate-strategic
179
+ key fp: 3ecb62b07e0b0984
180
+
181
+ ✓ Checkpoints: 12/12 valid
182
+ [ok] cp_a846e749 — ok
183
+ [ok] cp_b912f3e2 — ok
184
+ ...
185
+
186
+ ✓ Events: 2612/2612 valid
187
+ All events verified.
188
+
189
+ ✓ Checkpoint→event binding: 12/12 checkpoints bound to exported events
190
+
191
+ ✓ Forensic Confidence: attested 91.3 (A-) — recomputed 91.3 (A-) from the signed signal inputs
192
+
193
+ Verdict: CLEAN (exit code 0)
194
+ ```
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,56 @@
1
+ """Setup for trustflash-verify.
2
+
3
+ Distributable as `pip install trustflash-verify`. Single-script tool;
4
+ console_scripts entry point makes `trustflash-verify` available on PATH
5
+ after install.
6
+ """
7
+
8
+ from setuptools import setup
9
+
10
+ with open("README.md", "r", encoding="utf-8") as f:
11
+ long_description = f.read()
12
+
13
+ setup(
14
+ name="trustflash-verify",
15
+ version="0.4.0",
16
+ description=(
17
+ "Open-source forensic verifier for TrustSHIELD/AIREC TrustFlash "
18
+ "audit-export bundles. Verifies Ed25519 checkpoint signatures, the "
19
+ "SHA-256 event hash chain, checkpoint-to-event binding, and the "
20
+ "signed Forensic Confidence score offline, no platform access "
21
+ "required."
22
+ ),
23
+ long_description=long_description,
24
+ long_description_content_type="text/markdown",
25
+ author="Northgate Strategic LLC",
26
+ author_email="support@northgatestrategic.com",
27
+ url="https://github.com/northgate-strategic/trustflash-verifier",
28
+ license="MIT",
29
+ py_modules=["trustflash_verify"],
30
+ python_requires=">=3.10",
31
+ install_requires=[
32
+ "cryptography>=41.0.0",
33
+ ],
34
+ extras_require={
35
+ "dev": ["pytest>=7"],
36
+ },
37
+ entry_points={
38
+ "console_scripts": [
39
+ "trustflash-verify=trustflash_verify:main",
40
+ ],
41
+ },
42
+ classifiers=[
43
+ "Development Status :: 4 - Beta",
44
+ "Intended Audience :: Information Technology",
45
+ "Intended Audience :: Legal Industry",
46
+ "License :: OSI Approved :: MIT License",
47
+ "Operating System :: OS Independent",
48
+ "Programming Language :: Python :: 3",
49
+ "Programming Language :: Python :: 3.10",
50
+ "Programming Language :: Python :: 3.11",
51
+ "Programming Language :: Python :: 3.12",
52
+ "Topic :: Security :: Cryptography",
53
+ "Topic :: System :: Logging",
54
+ ],
55
+ keywords="audit forensic verification ed25519 sha256 ai-governance trustshield",
56
+ )