Skip to main content

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

  1. Fetch — Retrieve evidence record from the Strix proof API
  2. Reconstruct — Build canonical 13-field payload (locked field order)
  3. Fetch key — Resolve Ed25519 public key from JWKS endpoint
  4. Verify signature — Ed25519 signature over canonical payload
  5. Verify hash — SHA-256 hash of canonical payload
  6. Derive compliance flags — EU AI Act flags derived from outcomes (never asserted)
  7. ReturnVerificationResult with 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() returns False
  • Sync and async HTTP clients available for all network operations

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

strix_verify-0.2.0.tar.gz (33.2 kB view details)

Uploaded Source

Built Distribution

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

strix_verify-0.2.0-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

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

Hashes for strix_verify-0.2.0.tar.gz
Algorithm Hash digest
SHA256 7f49fea1a2ff0788ef9cff3d3e544cfdd11b1b96af9ca18b8720ac6d3e545882
MD5 b92aad7a161c89d7979dad0b8b5c5f73
BLAKE2b-256 83df1a936e287cfa7ffd0a557f7bcbb758f6b9d2ba6f73827e99589cf4f5d212

See more details on using hashes here.

Provenance

The following attestation bundles were made for strix_verify-0.2.0.tar.gz:

Publisher: publish-strix-verify.yml on Tarshann/strix-platform

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for strix_verify-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3a3990dcdd829495e9497ac4950ede528147c1cf4efbdea2d89db77f69afef01
MD5 80d6ad17ad209aa6dbd3feeb0cec5934
BLAKE2b-256 11bb27c273187211aa4d310182c8a35c68aa5b9aa1046a15ee045c24add5f567

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page