Skip to main content

ODIN Open Proof Envelope (OPE): canonical JSON, CID hashing, Ed25519 signatures, verifiable envelopes & bundles

Project description

ODIN OPE (Open Proof Envelope)

Lightweight, production-grade primitives for verifiable AI↔AI / AI↔Human communication.
This package gives you deterministic canonical JSON, CID hashing, Ed25519 signatures, and helpers to build/verify envelopes & export bundles used across the ODIN ecosystem.

  • Deterministic canonical JSON → stable hashes and signatures
  • CID: sha256:<hex> computed over canonical bytes
  • Envelope signing: sign "{cid}|{trace_id}|{ts}" with Ed25519
  • Bundle signing: sign "{bundle_cid}|{trace_id}|{exported_at}"
  • Signer backends: local seed (default). Optional extras for GCP KMS / AWS KMS / Azure KV.

Install

pip install odin-ope
# or with extras: pip install "odin-ope[gcpkms]"  # etc.

Quick start

from odin_ope.signers import FileSigner
from odin_ope.envelope import build_envelope, sign_envelope
from odin_ope.verify import verify_envelope, build_jwks_for_signers
from odin_ope.bundle import build_bundle, sign_bundle, verify_bundle

# 1. Create a signer (Ed25519, deterministic seed for demo)
seed_b64u = "A"*43  # 32-byte Ed25519 seed as base64url (example placeholder)
signer = FileSigner(seed_b64u=seed_b64u)  # kid derived from public key

# 2. Build and sign an envelope
payload = {"invoice_id": "INV-1", "amount": 100.25, "currency": "USD"}
env = build_envelope(payload, payload_type="openai.tooluse.invoice.v1", target_type="invoice.iso20022.v1")
signed_env = sign_envelope(env, signer)

# 3. Build JWKS and verify the envelope
jwks = build_jwks_for_signers([signer])

ok, reason = verify_envelope(signed_env, jwks)
assert ok, reason  # (or use verify_envelope_or_raise for exceptions)

# 4. Create and sign a bundle
receipts = [
    {"hop": 0, "receipt_hash": "h0", "prev_receipt_hash": None},
    {"hop": 1, "receipt_hash": "h1", "prev_receipt_hash": "h0"}
]
bundle = build_bundle(trace_id=signed_env["trace_id"], receipts=receipts)
sig = sign_bundle(bundle, signer)
ok2, reason2 = verify_bundle(bundle, sig, jwks, kid=signer.kid)
assert ok2, reason2

See examples/end_to_end.py for a full, annotated script.


FAQ: Common errors

Q: ModuleNotFoundError: No module named 'odin_ope' A: Make sure your PYTHONPATH includes the src directory, or install the package in editable mode: pip install -e .

Q: ValueError: Ed25519 seed must be 32 bytes A: The seed for FileSigner must be a base64url-encoded string representing exactly 32 bytes.

Q: Envelope verification fails with cid_mismatch A: The payload was likely modified after signing. Always verify before mutating envelopes.

Q: How do I generate a valid Ed25519 seed? A: Use os.urandom(32) and encode with base64.urlsafe_b64encode(seed).rstrip(b'=').

Q: How do I run the tests? A: PYTHONPATH=src pytest (or on Windows: $env:PYTHONPATH='src'; python -m pytest)

Reason Codes

Code Meaning
cid_mismatch Payload hash changed after signing
missing_sig_or_kid Envelope missing sender_sig or kid
kid_not_found KID not present in supplied JWKS
signature_invalid Signature verification failed
timestamp_skew ts outside allowed skew window
schema_error Structural or field validation error
not_yet_valid not_before is in the future
expired expires_at is in the past

These map 1:1 to exception subclasses (see odin_ope.exceptions).

CLI

The package installs a odin-ope CLI:

odin-ope sign-envelope --payload payload.json --payload-type t --target-type tgt --seed <base64url-seed>
odin-ope verify-envelope --envelope env.json --jwks jwks.json --json --max-skew 300 --strict

Use --json for structured output and --no-skew to disable time skew checks.

Development

Install dev extras and run tests + type checking:

pip install -e .[dev]
pytest -q
mypy src/odin_ope
python scripts/gen_sbom.py --out sbom.json  # generate CycloneDX SBOM

Programmatic version: import odin_ope; print(odin_ope.__version__). \n+## Development \n+Install dev extras and run tests + type checking: \n+``` pip install -e .[dev] pytest -q mypy src/odin_ope

## Publishing
## Publishing

A GitHub Actions workflow is included (`.github/workflows/publish.yml`).  
Create a repository, push, add `PYPI_API_TOKEN` secret, then tag a release like `v0.9.0`.
The workflow produces:
- Signed artifacts published to PyPI
- CycloneDX SBOM artifact (download from workflow run)
- Build provenance attestation (GitHub Attestations UI / API)

---

## License

Apache-2.0

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

odin_ope-0.9.0.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

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

odin_ope-0.9.0-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file odin_ope-0.9.0.tar.gz.

File metadata

  • Download URL: odin_ope-0.9.0.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for odin_ope-0.9.0.tar.gz
Algorithm Hash digest
SHA256 96575b727e418d1a4544c4dbd7a10ecd4c2a0c1b94a7fc630421012f8e5546cc
MD5 f9f5b8119526e45dd072dc535f7fdd16
BLAKE2b-256 44eb9008ecff71a917591b58019d8b957bbbbb95a66f2846bec45b4ade87d208

See more details on using hashes here.

File details

Details for the file odin_ope-0.9.0-py3-none-any.whl.

File metadata

  • Download URL: odin_ope-0.9.0-py3-none-any.whl
  • Upload date:
  • Size: 15.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for odin_ope-0.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6f96cc3af5bb511d3b4e90269a0f5048c1d78f1118b7435eec312f4d8e773c34
MD5 ec2a6809c796c39184e305398e22edab
BLAKE2b-256 aa5dd2796487acda128af30881d0047f9c330f74f1a148840f27dda999d03301

See more details on using hashes here.

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