Catalog PyPI
PACKAGE EXPLORERView in registry

aetherproof

PyPI

AetherProof - the open-source receipt engine. Prototype of Signet.

aiauditcompliancecryptographyed25519receipttamper-proof
Versions collected1
Direct dependencies7From release 0.5.1
Last observed20 Oct, 20:55 UTC

README

Version 0.5.1 documentation

Signet

AetherProof

Cryptographic receipts for AI output. Prove a model's output has not been modified - no server, no account, verifiable offline forever.

pip install aetherproof

Not a developer? Start with the plain-language guide

  • first receipt in three steps, no code.

The problem

Somebody acts on an AI's output. Weeks later it is questioned:

"Did it really say that, or did you change it afterwards?"

Today that argument is unwinnable in both directions. You cannot prove you did not edit a text file, and they cannot prove you did. Screenshots prove nothing. Logs you control prove nothing, because you control them.

AetherProof turns that into arithmetic that either checks or does not.


Use it

Sign one output

from aetherproof.auto import sign

resp = client.chat.completions.create(model="gpt-4o", messages=[...])
out  = resp.choices[0].message.content

sign(prompt=user_prompt, output=out, model_id=resp.model)

That is the whole integration. It never prompts, never blocks. On failure it returns None and your program continues - set AETHERPROOF_STRICT=1 if a missing receipt should be an error instead.

Wrap a function you already have

from aetherproof.auto import receipted

@receipted(model_id="gpt-4o")
def ask(prompt: str) -> str:
    return client.chat.completions.create(...).choices[0].message.content

No call sites change.

A whole conversation, one signature

from aetherproof.auto import AutoSession

with AutoSession(model_id="gpt-4o") as chat:      # seals on exit
    for prompt in prompts:
        chat.turn(prompt=prompt, output=ask(prompt))

At 1,000 turns that is one 412-byte seal. Proving any single turn costs 10 hashes and about 1 KB, and reveals nothing about the other 999.

From the command line

aetherproof sign model.onnx output.txt
aetherproof verify receipt.json --output output.txt
aetherproof                                   # interactive menu

More recipes: docs/INTEGRATION.md - pick a path by one question, every snippet tested.


Verify it

Verification needs 21 lines and one dependency. No network, no account, no special hardware, and it keeps working if this project is abandoned.

pip install cryptography      # that is the entire requirement

The shape of it, so you can see there is no trick - this is illustrative, not complete:

from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
import json

r   = json.load(open("receipt.json"))
pub = Ed25519PublicKey.from_public_bytes(bytes.fromhex(r["public_key"]))

# every field length-prefixed as "<len>:<field>", concatenated, then signed
preimage = build_preimage(r)                 # see the full version below
pub.verify(bytes.fromhex(r["signature"]), preimage)     # raises if invalid

Do not ship the snippet above. It omits log_sequence, hw_evidence, the v1.2 extension commitment, and the v1.3 receipt_id and signing_key_id, so it rejects every receipt the current version produces. The complete verifier - 21 lines, tested on every commit against real receipts - is in docs/VERIFICATION.md.


What it proves

ClaimMechanism
This exact output was not modified after signingoutput_hash inside the signed preimage
The receipt itself was not alteredEd25519 over a length-prefixed canonical preimage
It was signed by the holder of a specific keyEd25519 verify, no other input
A claimed time and log position were fixed at signingboth inside the preimage
The local log was not edited, reordered, or truncated in the middlekey-free hash chain
A specific turn belongs to a sealed sessionMerkle inclusion proof, revealing no other turn
Anyone can check all of it offline, foreverreceipt + public key, nothing else

What it does not prove

Read this before citing anything above.

Integrity, not completeness. "Show me the record of this decision" is answered. "Show me that you logged them all" is not. Someone who logs 9,000 of 10,000 outputs passes every check here. That cannot be fixed locally - it needs an independent witness, which does not exist yet.

Not provenWhy
That the named model produced the outputit signs a (model, output) pair you supply
That the timestamp is truthfulit is your own clock - bound, not externally anchored
That the signing key is held securelya software key on disk unless you set a passphrase
That it survives a quantum adversaryPython is Ed25519 only; ML-DSA-65 is in the Rust core

Where it does not fit at all: detecting deepfakes or unsigned AI content. A scammer never signs, so there is nothing to verify.

Full list: docs/CLAIMS.md.


Two implementations

Rust - rust/Python - aetherproof/
Receipt128 B fixed binary646 B JSON
Post-quantumML-DSA-65 (FIPS 204)none
Secret zeroization, constant-time compareyesno
unsafe in productionzero, compiler-enforcedn/a
Tests59642 (93% coverage)
Distributionsource + CI wheelsPyPI

Measured, 50,000 leaves, medians of seven isolated runs: Rust builds a Merkle tree in 28.16 ms against Python's 102.71 ms (3.6x) and verifies a proof in 3.93 µs against 17.17 µs (4.4x).

The Rust core is optional. aetherproof does not import it and behaves identically without it - enforced in CI. See docs/ROADMAP.md.

Secrets that get wiped

A signing key held as a Python bytes object cannot be wiped - it is immutable, and garbage collection does not overwrite the allocation. SecureSigner keeps the key inside Rust and overwrites it on release, including when a block exits by exception.

import _native

with _native.SecureSigner() as signer:        # key wiped on exit
    pub     = signer.public_key()             # nothing returns the secret
    receipt = signer.sign_receipt(pid=1, binary=model_bytes,
                                  memory_hash=0, syscall_count=1)

assert _native.SecureVerifier(pub).verify_receipt(receipt)

Setup and post-quantum usage: docs/INTEGRATION.md.


Documentation

INTEGRATION.mdstart here - pick a path by one question
GETTING-STARTED.mdfirst receipt, no code
CLAIMS.mdwhat this proves and what it does not
VERIFICATION.mdthe offline verifier, in full
CLOUD-MODELS.mdlocal weights vs an API you do not control
AGENT-CHAIN.mdbinding agent context (receipt v1.2)
SECURITY.mdreporting a vulnerability, threat model, known issues
ROADMAP.md0.5.x - Rust core, bindings, post-quantum
ANALYSIS.mdmeasured assessment, including what is unverified
CONTRIBUTING.mdextension and spec workflow
RELEASE-NOTES-0.5.1.mdwhat changed in 0.5.1
RELEASE-NOTES-0.4.0.mdwhat changed in 0.4.0
agent-chain-context-response.mdthe v1.2 design discussion, from issue #1
DEMO.mdrecording a walkthrough

License

Apache-2.0. Use it, deploy it, fork it, embed it in a commercial product - no copyleft obligation. The receipt format and the offline verifier are meant to be copied freely; a proof layer nobody can adopt is not a proof layer.

Versions up to 0.2.2 were AGPL-3.0-or-later. From 0.3.0 onward: Apache-2.0.

Security issues: SECURITY.md - please do not open a public issue.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.5.119 Aug 20267

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 20:55 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:c42c6e481a407efa62fbf2f610b8d6a8d24d60d4fd99f1a1da38ed5e19668471