Independent verification of Strix governance evidence records. Ed25519 + SHA-256 only. No Strix tooling or account required. Public source at github.com/strixgov/strix.
Project description
strix-verify
Independent verification of Strix governance evidence records.
No Strix tooling, SDK, or account required. Uses only standard cryptographic
primitives (Ed25519, SHA-256) via the Python cryptography library.
strix-verify is offline-safe. Save the JWKS once, ship it with the evidence, verify on an air-gapped machine. No callbacks. No telemetry. No Strix server required at runtime.
Proof Readiness Level 4.5 — Cryptographically Signed + Externally Verifiable
Public source: github.com/strixgov/strix PyPI: pypi.org/project/strix-verify
Installation
pip install strix-verify
Or from source:
cd python/strix-verify
pip install -e .
Quick Start
from strix_verify import verify_evidence
result = verify_evidence(
evidence_id=123,
proof_base="https://strix.example.com", # your Strix deployment
jwks_base="https://strixgov.com", # canonical JWKS surface
)
print(result.signature_valid) # SignatureStatus.VERIFIED
print(result.hash_valid) # True
print(result.compliance.article12_tamper_resistant) # True
print(result.compliance.article14_human_oversight) # True
print(result.compliance.article28_provider_obligations) # True
proof_base is required — there is no default. The verifier is neutral
across Strix deployments and never carries a hardcoded host URL.
Async
import asyncio
from strix_verify import fetch_evidence_async, verify_evidence_record
async def main():
record = await fetch_evidence_async(123, proof_base="https://strix.example.com")
result = verify_evidence_record(record, jwks_base="https://strixgov.com")
return result
asyncio.run(main())
Verification Flow
- Fetch — Retrieve evidence record from the Strix proof API
- Reconstruct — Build canonical 13-field payload (locked field order)
- Fetch key — Resolve Ed25519 public key from JWKS endpoint
- Verify signature — Ed25519 signature over canonical payload
- Verify hash — SHA-256 hash of canonical payload
- Derive compliance flags — EU AI Act flags derived from outcomes (never asserted)
- Return —
VerificationResultwith all outcomes
Two-Layer Verification Model
Layer 1 — Cryptographic Validity (signature_valid)
"Was this record produced by the holder of the Strix signing key?"
| Status | Meaning |
|---|---|
VERIFIED |
Valid Ed25519 signature from a known key |
LEGACY_UNSIGNED |
Pre-signing record (migration before 0039) |
UNVERIFIABLE_KEY |
Signing key ID not found in JWKS or extra_keys |
COMPLIANCE_VIOLATION |
Signature present but invalid |
ERROR |
Network or unexpected failure |
Layer 2 — Deployment Context (environment_match, tenant_match)
"Is this record appropriate for this deployment context?"
Optional checks against stored record fields. Per SE-14, verification reads
environment and tenantId from the stored evidence record — never from
environment variables. This prevents false failures when a production record is
verified in a development context.
result = verify_evidence(
evidence_id=123,
expected_environment="production", # checks stored record field
expected_tenant_id="tenant-abc", # checks stored record field
)
print(result.environment_match) # True/False/None
print(result.tenant_match) # True/False/None
Verifying a Local Record
If you already have the evidence record dict (from a database, file, etc.):
from strix_verify import verify_evidence_record
result = verify_evidence_record(
record,
jwks_base="https://strixgov.com",
)
Verifying Offline (Air-Gapped)
For audit environments that cannot reach the internet, pre-fetch the JWKS once, save it next to the evidence, and verify with no network access at runtime:
import json
from strix_verify import verify_evidence_record
with open("evidence-2026-04-19.json") as f:
record = json.load(f)
with open("jwks-snapshot-2026-04.json") as f:
extra_keys = json.load(f)["keys"]
result = verify_evidence_record(
record,
extra_keys=extra_keys,
jwks_base="https://unused.invalid", # never reached when key is in extra_keys
)
When the signing key is already present in extra_keys, jwks_base is
never contacted. The verifier resolves the key from the pre-fetched JWK
list and does the full cryptographic check locally.
Key Rotation Support
Historical signing keys can be provided to verify older records after key rotation:
import json, os
extra_keys = json.loads(os.environ.get("STRIX_SIGNING_JWKS_EXTRA", "[]"))
result = verify_evidence(
evidence_id=123,
extra_keys=extra_keys,
)
Key ID format: strix-{env}-{YYYY-MM} (e.g., strix-prod-2026-04). EU AI Act
compliance requires a minimum 2-year key retention period.
EU AI Act Compliance Flags
Compliance flags are derived from verification outcomes — never read from stored
fields (invariant CI-5). Altering the regulatoryContext block in a signed record
invalidates the Ed25519 signature.
| Flag | Derived From |
|---|---|
article12_tamper_resistant |
hash_valid AND chain_valid AND signature_valid == VERIFIED |
article14_human_oversight |
signature_present (actor fields cryptographically bound) |
article28_provider_obligations |
signature_valid == VERIFIED (evidence from known key) |
Canonical Payload Schema
The 13-field locked-order payload that is signed and hashed:
schemaVersion (always "1")
evidenceId
evidenceHash
proofChainHash
capabilityId
action
actorId
actorRole
createdAt
signingKeyId
environment
tenantId
regulatoryContext { complianceMode, euAiActArticle12, euAiActArticle14, euAiActArticle28 }
Warning: Reordering these fields invalidates all existing signatures. This schema
is locked and versioned. See tests/test_payload.py::test_golden_vector for the
canonical serialization canary.
JWKS Endpoint
Public keys are served at:
GET https://strixgov.com/.well-known/strix-jwks.json
GET https://strixgov.com/.well-known/strix-jwks.json?kid=strix-prod-2026-04
The endpoint follows RFC 7517. Each key is an OKP/Ed25519 JWK with a kid in
strix-{env}-{YYYY-MM} format.
Development
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run tests with coverage
pytest --cov=strix_verify --cov-report=term-missing
# Lint
ruff check src/ tests/
# Type check
mypy src/
Architecture Notes
- No Strix SDK dependency — pure Python +
cryptography+httpx - Ed25519 SPKI DER construction matches the TypeScript implementation exactly:
12-byte header
302a300506032b6570032100+ 32 raw key bytes - Never raises on bad signatures —
verify_signature()returnsFalse - Sync and async HTTP clients available for all network operations
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
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 strix_verify-0.2.0.tar.gz.
File metadata
- Download URL: strix_verify-0.2.0.tar.gz
- Upload date:
- Size: 33.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f49fea1a2ff0788ef9cff3d3e544cfdd11b1b96af9ca18b8720ac6d3e545882
|
|
| MD5 |
b92aad7a161c89d7979dad0b8b5c5f73
|
|
| BLAKE2b-256 |
83df1a936e287cfa7ffd0a557f7bcbb758f6b9d2ba6f73827e99589cf4f5d212
|
Provenance
The following attestation bundles were made for strix_verify-0.2.0.tar.gz:
Publisher:
publish-strix-verify.yml on Tarshann/strix-platform
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strix_verify-0.2.0.tar.gz -
Subject digest:
7f49fea1a2ff0788ef9cff3d3e544cfdd11b1b96af9ca18b8720ac6d3e545882 - Sigstore transparency entry: 1710127524
- Sigstore integration time:
-
Permalink:
Tarshann/strix-platform@2a38aaef4a38f5af6e86c960d4a573bd7f7afe1f -
Branch / Tag:
refs/tags/strix-verify-v0.2.0 - Owner: https://github.com/Tarshann
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-strix-verify.yml@2a38aaef4a38f5af6e86c960d4a573bd7f7afe1f -
Trigger Event:
push
-
Statement type:
File details
Details for the file strix_verify-0.2.0-py3-none-any.whl.
File metadata
- Download URL: strix_verify-0.2.0-py3-none-any.whl
- Upload date:
- Size: 17.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a3990dcdd829495e9497ac4950ede528147c1cf4efbdea2d89db77f69afef01
|
|
| MD5 |
80d6ad17ad209aa6dbd3feeb0cec5934
|
|
| BLAKE2b-256 |
11bb27c273187211aa4d310182c8a35c68aa5b9aa1046a15ee045c24add5f567
|
Provenance
The following attestation bundles were made for strix_verify-0.2.0-py3-none-any.whl:
Publisher:
publish-strix-verify.yml on Tarshann/strix-platform
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strix_verify-0.2.0-py3-none-any.whl -
Subject digest:
3a3990dcdd829495e9497ac4950ede528147c1cf4efbdea2d89db77f69afef01 - Sigstore transparency entry: 1710127588
- Sigstore integration time:
-
Permalink:
Tarshann/strix-platform@2a38aaef4a38f5af6e86c960d4a573bd7f7afe1f -
Branch / Tag:
refs/tags/strix-verify-v0.2.0 - Owner: https://github.com/Tarshann
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-strix-verify.yml@2a38aaef4a38f5af6e86c960d4a573bd7f7afe1f -
Trigger Event:
push
-
Statement type: