Python implementation of the GuardSpine kernel -- evidence-bundle verification and sealing.
Produces byte-identical hashes to the TypeScript reference (@guardspine/kernel) and the Lean 4 formal verification backend. All three implementations use RFC 8785 canonical JSON serialization and are validated against shared golden vectors from guardspine-spec.
| Language | Package | Purpose |
|---|---|---|
| TypeScript | @guardspine/kernel | Reference implementation (canonical) |
| Python (this repo) | guardspine-kernel |
Python integrations (FastAPI, CLI, ML pipelines) |
| Lean 4 | guardspine-lean | Formally verified backend |
v0.2.1 adds optional sanitization metadata (PII/secret redaction attestation). The proof format is unchanged from v0.2.0.
pip install guardspine-kernelFrom source:
pip install -e ".[dev]"Requires Python 3.10+. Single runtime dependency: cryptography>=42.0.0.
from guardspine_kernel import seal_bundle
items = [
{
"item_id": "audit-001",
"content_type": "guardspine/audit_event",
"content": {"action": "user_login", "user_id": "u123"},
},
{
"item_id": "audit-002",
"content_type": "guardspine/audit_event",
"content": {"action": "data_access", "resource": "customers"},
},
]
result = seal_bundle(items)
print(result.immutability_proof.root_hash)
# sha256:...from guardspine_kernel import verify_bundle
bundle = {
"bundle_id": "bundle-001",
"version": "0.2.0",
"created_at": "2026-01-15T10:30:00.000Z",
"items": [...],
"immutability_proof": {...},
}
result = verify_bundle(bundle)
if result.valid:
print("Bundle is valid!")
else:
for error in result.errors:
print(f"{error.code}: {error.message}")from guardspine_kernel import canonical_json
# RFC 8785 compliant JSON serialization
obj = {"z": 1, "a": 2}
print(canonical_json(obj)) # {"a":2,"z":1}The lean_shim module delegates cryptographic operations to a compiled Lean 4 binary via subprocess. This provides formally verified canonical JSON, content hashing, bundle sealing, and bundle verification -- the same operations the Python code performs, but with machine-checked correctness proofs.
- RFC 8785 canonical JSON serialization
- SHA-256 content hashing of canonicalized payloads
- Evidence bundle sealing with hash chains and root hashes
- Bundle verification (hash/chain/root integrity checks)
Signature verification is not yet implemented in Lean. When require_signatures=True, the shim falls back to the Python implementation.
The shim communicates with the Lean binary over stdin/stdout:
guardspine <entrypoint>
- CLI argument = entrypoint name (
canonical_json,compute_content_hash,seal_bundle,verify_bundle) - stdin = JSON payload (one line)
- stdout =
{"ok": true, "result": ...}on success,{"ok": false, "error": "..."}on failure - Exit code = 0 on success, non-zero on crash
- Timeout = 30 seconds per call
- Build the Lean binary from the guardspine-lean repo:
cd guardspine-lean
lake build guardspineThis produces a native binary (e.g., .lake/build/bin/guardspine on Linux/macOS, .lake\build\bin\guardspine.exe on Windows).
- Set the environment variable to point at the built binary:
export GUARDSPINE_LEAN_BIN=/path/to/guardspine-lean/.lake/build/bin/guardspineGUARDSPINE_LEAN_EXE is accepted as an alias.
- The shim auto-activates when imported. If the env var is unset or the binary is missing,
lean_shimraisesImportError. Callers can catch this and fall back to the pure-Python implementation:
try:
from guardspine_kernel.lean_shim import seal_bundle, verify_bundle
except ImportError:
from guardspine_kernel import seal_bundle, verify_bundletests/test_lean_parity.py runs the same scenarios through both the Lean shim and the Python implementation, asserting byte-identical hashes. These tests skip automatically when the Lean binary is not available.
GUARDSPINE_LEAN_BIN=/path/to/guardspine pytest tests/test_lean_parity.py -vSecurity measures matching the TypeScript kernel:
- Seal validation guards:
seal_bundlevalidatesitem_idandcontent_typepresence before processing, raisesValueErrorwith the offending index - Max chain items:
build_hash_chainrejects inputs exceeding 10,000 items - Proof version support: both
v0.2.0(current) andlegacy(deprecated 3-field chain hash) - Non-empty items:
seal_bundleraises on empty items list - Version enforcement:
verify_bundlerejects versions other than"0.2.0"or"0.2.1"
verify_signatures supports the same algorithms as the TypeScript kernel:
| Algorithm | Implementation |
|---|---|
ed25519 |
cryptography library Ed25519 verification |
rsa-sha256 |
RSA PKCS1v15 with SHA-256 |
ecdsa-p256 |
ECDSA with SECP256R1 and SHA-256 |
hmac-sha256 |
hmac.compare_digest with shared secret |
Public keys are passed via public_keys dict (key_id -> PEM string). HMAC secrets via hmac_secret parameter.
seal_bundle(items, options, bundle_id, version, created_at)-- Seal items into a bundle dictbuild_hash_chain(items, options)-- Build hash chain fromChainInputlistcompute_content_hash(content)-- SHA-256 of canonical JSON ("sha256:<hex>")compute_root_hash(chain)-- Root hash over concatenated chain hashes
verify_bundle(bundle, ...)-- Full bundle verification (fields, content, chain, root, cross-check, signatures)verify_hash_chain(chain, ...)-- Verify chain linkage and recompute chain hashesverify_root_hash(proof)-- Verify root hash matches chainverify_content_hashes(items)-- Verify item content hashes via canonical JSONverify_signatures(bundle, ...)-- Verify Ed25519/RSA/ECDSA/HMAC signatures
All error codes match @guardspine/kernel/errors.ts:
| Code | Meaning |
|---|---|
MISSING_REQUIRED_FIELD |
Bundle missing required field |
UNSUPPORTED_VERSION |
Bundle version not "0.2.0" or "0.2.1" |
INPUT_VALIDATION_FAILED |
Invalid input format |
CONTENT_HASH_MISMATCH |
Content hash does not match |
HASH_CHAIN_BROKEN |
Chain linkage broken |
ROOT_HASH_MISMATCH |
Root hash does not match |
SEQUENCE_GAP |
Sequence numbers have gaps |
LENGTH_MISMATCH |
Items count != chain length |
SIGNATURE_INVALID |
Signature verification failed |
SIGNATURE_REQUIRED |
Bundle must have signatures |
pytest tests/test_parity.py -vGolden vectors are stored in ../guardspine-spec/fixtures/golden-vectors/.
Apache-2.0