Offline evidence-bundle verification and sealing for GuardSpine (Python)
Project description
guardspine-kernel-py
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 Implementations
| 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.
Installation
pip install guardspine-kernel
From source:
pip install -e ".[dev]"
Requires Python 3.10+. Single runtime dependency: cryptography>=42.0.0.
Usage
Sealing a Bundle
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:...
Verifying a Bundle
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}")
Canonical JSON
from guardspine_kernel import canonical_json
# RFC 8785 compliant JSON serialization
obj = {"z": 1, "a": 2}
print(canonical_json(obj)) # {"a":2,"z":1}
Lean Shim (Formal Verification Backend)
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.
What the Lean binary provides
- 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.
Subprocess bridge protocol
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
Setup
- Build the Lean binary from the guardspine-lean repo:
cd guardspine-lean
lake build guardspine
This 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/guardspine
GUARDSPINE_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_bundle
Parity testing
tests/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 -v
Hardening
Security 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"
Signature Verification
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.
API Reference
Sealing
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
Verification
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
Error Codes
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 |
Cross-Language Parity
pytest tests/test_parity.py -v
Golden vectors are stored in ../guardspine-spec/fixtures/golden-vectors/.
License
Business Source License 1.1 (source-available) -- see LICENSE. Free for non-commercial, evaluation, and small-organization use (annual revenue under USD 1,000,000); other production use requires a commercial license from GuardSpine, Inc. Each version converts to Apache-2.0 four years after its release.
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 guardspine_kernel-2.0.0.tar.gz.
File metadata
- Download URL: guardspine_kernel-2.0.0.tar.gz
- Upload date:
- Size: 23.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5498279ccdb9f71651e6fb5964545225cb97e8a999ee2d2dc89153407006626
|
|
| MD5 |
8f621fbdb07d0d3804c1a27e0586d218
|
|
| BLAKE2b-256 |
893fdd665ce82e9fe18eb2391257a43ca432b4ef3bedad7abb7d42b490cd2dc7
|
File details
Details for the file guardspine_kernel-2.0.0-py3-none-any.whl.
File metadata
- Download URL: guardspine_kernel-2.0.0-py3-none-any.whl
- Upload date:
- Size: 20.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e2cb6f61b84228783b5c550ea8b7c8acd0af84a8cc0d98beeb1be64120edac7
|
|
| MD5 |
500f036b1ccf5d39656676018097cf3f
|
|
| BLAKE2b-256 |
342c2d5c71db12680d49b9f19621694137b28957ab6dd4363f0315f80a460dd3
|