Standalone verifier for Marturia (Plumb v2) cryptographic audit receipts.
Project description
marturia-verify
Standalone verifier for Marturia cryptographic audit receipts.
Anyone holding a Marturia receipt and the issuing tenant's public key can verify the receipt without trusting the Marturia infrastructure that issued it. That's the point: cryptographic testimony you can audit independently.
Install
pip install marturia-verify
The only runtime dependency is cryptography.
CLI
# Verify a single receipt
marturia-verify --receipt receipt.json --pubkey tenant.pub
# → VALID: signature valid; receipt_hash matches; sequence 42 of tenant 12
# Verify a contiguous chain
marturia-verify --chain receipts.json --pubkey tenant.pub
# → VALID: chain valid: 27 receipt(s), seq 1..27
# Public key inline as hex
marturia-verify --receipt receipt.json --pubkey-hex 4f3a...64hex...
# Quiet mode (one-line output)
marturia-verify --chain receipts.json --pubkey tenant.pub --quiet
Exit code: 0 on success, 1 on any verification failure.
Library API
from marturia_verify import verify_receipt, verify_chain
# Single receipt
result = verify_receipt(receipt_dict, public_key_bytes)
if not result.valid:
raise RuntimeError(result.reason)
# Chain — public_key must match the signing key for every receipt in the
# chain. If your chain crosses a key rotation, split it at the boundary
# and verify each segment with its own public key.
chain_result = verify_chain(receipts, public_key_bytes)
print(chain_result) # VerifyResult(valid=True, reason=..., receipt_seq=27)
Both functions return a VerifyResult — a frozen dataclass with .valid, .reason, .receipt_seq, .tenant_id. It's also truthy/falsy, so if not result: works.
Receipt format
A Marturia receipt is a JSON object with these fields:
| Field | Type | Notes |
|---|---|---|
payload_canonical_bytes |
hex or base64 string | The exact bytes that were signed. NOT the deserialised payload — the canonical-JSON-encoded version with sorted keys, no whitespace, embedded schema/meta. |
tenant_id |
int | The Marturia tenant the receipt belongs to. Bound into the hash. |
receipt_seq |
int | Per-tenant monotonic sequence (1, 2, 3, ...). Bound into the hash. |
prev_hash |
hex string or null | SHA-256 of the previous receipt in this tenant's chain. null when receipt_seq == 1. |
receipt_hash |
hex string | `sha256(prev_hash |
signature |
hex string | Ed25519 signature of receipt_hash, raw 64 bytes hex-encoded. |
kid |
string (optional) | Signing key ID at signature time. Informational. |
What this verifier checks
For each receipt:
- All required fields are present
- The public key, signature, and stored
receipt_hashare well-formed - The recomputed
receipt_hashmatches the stored one (catches body modification) - The Ed25519 signature verifies against the public key (catches forgery)
For a chain (verify_chain):
receipt_seqis contiguous ascending with no gaps- Each receipt's
prev_hashmatches the previous receipt'sreceipt_hash(catches insertion / reordering / removal)
What it does NOT check:
- Witness cosignatures on Merkle roots — those are a separate transparency layer (see Marturia design doc 05). This package verifies the per-tenant chain; cosignature verification will land in a future release.
- Plan / billing / authorisation — that's enforced at issuance time, not in the receipt itself.
Why this exists
Every other observability vendor stores audit logs in a database they alone control. They could rewrite history and you'd never know. Marturia signs each event into a hash-chained ledger using a per-tenant Ed25519 key. The chain itself is rolled into Merkle roots that can be cosigned by independent witness peers — including your own customers, your own auditors, or third-party witnesses you trust. A compromised Marturia operator cannot forge history if any single witness cosigner is honest.
This package is the public verifier — anyone can check any receipt without our cooperation. That's the whole moat: cryptographic testimony you don't have to take our word for.
Versioning
The receipt format is _schema_v: 1 (visible in the payload_canonical_bytes payload). When Marturia eventually bumps to schema v2, this package will keep reading v1 receipts forever (they're permanent evidence) and add v2 support in a new minor release.
License
MIT.
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 marturia_verify-0.1.0.tar.gz.
File metadata
- Download URL: marturia_verify-0.1.0.tar.gz
- Upload date:
- Size: 13.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e600e0bc5c41bc363f01f07853823307104492c35c34c094352a0db79599818
|
|
| MD5 |
4115051a55c311da8b59b9a830de23cf
|
|
| BLAKE2b-256 |
dd37d429a440ea81c39d8a402a6891030089023d825d2646b501f3a8ebbe669b
|
File details
Details for the file marturia_verify-0.1.0-py3-none-any.whl.
File metadata
- Download URL: marturia_verify-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
493f12eb7879d6df361f0376b52a1fc723ed945a276024eee7f6a8edf3492bfd
|
|
| MD5 |
c6af487a9563d47ed4d7b46565b0612c
|
|
| BLAKE2b-256 |
77ca54037b3a2fc173fdcc36d46755ee2ddf520f9817e6869038c55f754f6459
|