Verification kernel for the ar.io verification stack: RFC 8785 canonicalization, SHA-256, Ed25519 envelope sign/verify, RFC 9162 Merkle inclusion proofs.
Project description
ar-io-proof
Verification kernel for the ar.io verification stack: RFC 8785 (JCS) canonicalization, SHA-256 hashing, Ed25519 envelope sign/verify, and RFC 9162 binary Merkle inclusion proofs — as a standalone, dependency-light Python package.
pip install ar-io-proof
Quickstart
Verify a signed envelope fetched from any Arweave gateway:
import json
import urllib.request
from ario_proof import verify_envelope
raw = urllib.request.urlopen("https://arweave.net/raw/<tx_id>").read()
result = verify_envelope(json.loads(raw))
assert result.ok # spec_version + payload binding + Ed25519 signature
print(result.to_dict())
Bind an artifact you hold to the provenance an envelope commits to (reverse lookup):
import hashlib
artifact_hash = hashlib.sha256(open("model.pkl", "rb").read()).hexdigest()
result = verify_envelope(envelope, expected_content_hash=artifact_hash)
print(result.content_hash_ok, result.content_role) # True, "asset"
Verify an external-commitment (ario.mlflow/v1) envelope against the committed bytes:
result = verify_envelope(envelope, payload_bytes=canonical_bytes)
Verify an inclusion-proof bundle (ariod proof output — proves a leaf was in a signed
daily checkpoint):
from ario_proof import verify_proof_bundle
bundle = json.load(open("proof-bundle.json"))
result = verify_proof_bundle(bundle)
assert result.ok and result.inclusion_ok
Sign an envelope (producers):
from ario_proof import sign_envelope, signing_key_from_seed_hex
key = signing_key_from_seed_hex("<32-byte seed hex>")
envelope = sign_envelope(
{
"spec_version": "ario.mlflow/v1",
"event_id": "...",
"event_type": "training_complete",
"subject": {"type": "mlflow_run", "run_id": "..."},
"payload_hash": "<sha256 of the committed canonical bytes>",
"previous_hash": "GENESIS",
"signed_at": "2026-06-10T00:00:00.000Z",
},
key,
)
What this package implements
- The Verifiable Event Envelope family contract,
envelope-spec.mdv1.1 (ratified v1.0 2026-06-10, amended 2026-06-11 — additive, same conformance corpus), for two profiles:ario.agent/v1— inline-payload envelopes minted byar-io-agent(byte-level format:docs/artifact.md).ario.mlflow/v1— external-commitment envelopes minted byar-io-mlflow.
- The RFC 9162 binary Merkle tree (leaf/node domain separation, audit paths, pinned
empty-tree root) and the
ario.agent.proof/v1inclusion-proof bundle behind agent verification checkpoints. - The accepted-version registry:
{ario.agent/v1, ario.mlflow/v1}, matched on thev<major>token boundary per envelope-spec §2 — additive minors (ario.agent/v1.3) are accepted within a major; different majors (ario.agent/v10) and malformed minors fail closed. Envelopes that predatespec_versionverify only with an explicitallow_legacy=True. - The signed scope per the ratified contract: the envelope minus
signature, minus the reservedco_signaturesfield (envelope-spec §7.1), and — forario.mlflow/v1and legacy envelopes only — minus underscore-prefixed annotation keys. Theario.agent/v1signed scope is minussignature/co_signaturesonly, matching the Go reference byte-for-byte.
The kernel is exactly the five primitives in the stack architecture's kernel scope — no I/O, no networking, no key lifecycle. Gateway fetching, attestation polling, and key storage belong to the products that import this.
Conformance
This package is conformance-gated against the ario.agent/v1 corpus at tag
test-vectors-v1.0, vendored under test-vectors/ byte-for-byte (see
test-vectors/VENDORING.md for provenance). CI asserts, for
every vector: JCS-canonical bytes, payload hashes, envelope-for-signature bytes,
deterministic signatures, Merkle roots, and audit paths — exact to the byte. If this
package disagrees with a vector, the package is wrong — never the vector.
mlflow-profile-specific behaviors (external commitment, underscore stripping, legacy
acceptance) are covered by unit tests; the bidirectional cross-product gate against
ar-io-mlflow's production verifier lands when mlflow migrates to import this package.
Trust model
result.ok proves: the holder of the private key matching the envelope's public_key
signed exactly these bytes, and the payload binding holds. It does not prove whose key
that is, or that the envelope is on Arweave — trust in the key comes from out of band (e.g.
the agent's registration chain), and on-chain presence comes from fetching the TX yourself
and re-verifying, which is exactly what the quickstart does. signed_at is the signer's
claim, not a trusted timestamp; witnessed time comes from the Arweave block.
Development
python3 -m venv .venv && .venv/bin/pip install -e .[dev]
.venv/bin/pytest -q # the conformance gate is the contract
.venv/bin/black src tests
Dependencies are deliberately two: PyNaCl (Ed25519,
strict RFC 8032 — matches Go crypto/ed25519 and the JS sibling verifier) and
jcs (reference RFC 8785).
License
MIT — verifier-relevant code is deliberately MIT-licensed so third-party auditors can verify independently of ar.io.
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 ar_io_proof-0.1.1.tar.gz.
File metadata
- Download URL: ar_io_proof-0.1.1.tar.gz
- Upload date:
- Size: 92.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5078a61a690a06de6f8ae2fd424dee86b24dded73670abd2abf79945de8ac0f
|
|
| MD5 |
0cac5f6c5a462b796e25e1177d65c611
|
|
| BLAKE2b-256 |
7300cb42a8a5afe043b95effc7872744ef3d94cbe627b99dd813068715303084
|
Provenance
The following attestation bundles were made for ar_io_proof-0.1.1.tar.gz:
Publisher:
release.yml on ar-io/ar-io-proof
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ar_io_proof-0.1.1.tar.gz -
Subject digest:
d5078a61a690a06de6f8ae2fd424dee86b24dded73670abd2abf79945de8ac0f - Sigstore transparency entry: 1785615040
- Sigstore integration time:
-
Permalink:
ar-io/ar-io-proof@ac21b64c5c82f608617a5e5c8f4288e10ddedcde -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/ar-io
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ac21b64c5c82f608617a5e5c8f4288e10ddedcde -
Trigger Event:
push
-
Statement type:
File details
Details for the file ar_io_proof-0.1.1-py3-none-any.whl.
File metadata
- Download URL: ar_io_proof-0.1.1-py3-none-any.whl
- Upload date:
- Size: 16.1 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 |
e3daf2951d5f9d91d92bec694a1eefdd576f4a1eb93ffd171d55bca6ddcf4317
|
|
| MD5 |
199bed90a9bcb9aa6cb32de958ca7814
|
|
| BLAKE2b-256 |
e5e2f0abee12c76e3541b4e1f3bdf3637fe522950f1355aea2d5d1195582c5e6
|
Provenance
The following attestation bundles were made for ar_io_proof-0.1.1-py3-none-any.whl:
Publisher:
release.yml on ar-io/ar-io-proof
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ar_io_proof-0.1.1-py3-none-any.whl -
Subject digest:
e3daf2951d5f9d91d92bec694a1eefdd576f4a1eb93ffd171d55bca6ddcf4317 - Sigstore transparency entry: 1785615134
- Sigstore integration time:
-
Permalink:
ar-io/ar-io-proof@ac21b64c5c82f608617a5e5c8f4288e10ddedcde -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/ar-io
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ac21b64c5c82f608617a5e5c8f4288e10ddedcde -
Trigger Event:
push
-
Statement type: