agent-toolprint (Rust)
Idiomatic Rust port of @p-vbordei/agent-toolprint. Double-signed receipts for AI-agent tool invocations — DSSE envelope + RFC 8785 JCS canonical payload + Ed25519. Verifiable offline. Byte-deterministic-compatible with the TypeScript reference.
Answers one audit question: "yes, agent X called tool Y with these args at T, both sides agree." Agent signs. Tool counter-signs. Anyone with the public keys verifies — no host, no service, no chain.
What's in the box
| Function | What it does |
|---|---|
sign_agent(&receipt, &sk) |
Validate, JCS-canonicalize, return DSSE envelope with agent sig. |
countersign_tool(&env, &sk) |
Verify envelope is JCS-canonical, append the tool signature. |
verify(&env, &opts).await |
Run all SPEC §4 checks; optionally re-hash plaintext. |
chain(&parent, &child) |
True iff child.parent == parent.id. |
DidKeyResolver |
Bundled did:key impl of the Resolver async trait. |
did_key_from_ed25519_pubkey(pk) / parse_did_key(did) |
Multicodec 0xed01 round-trip. |
sha256_hash(value) |
SHA-256 over JCS-canonical bytes, sha256:<hex>. |
canonical(value) |
RFC 8785 canonical JSON bytes. |
validate_receipt / validate_envelope |
Strict schema validators. |
PAYLOAD_TYPE / PROTOCOL_VERSION |
DSSE payloadType and the v field. |
Install
Rust 2021 (stable). Async via tokio (or any executor).
Quickstart
use ;
use ;
use SigningKey;
use OsRng;
use json;
async
# envelope signatures : 2
# original : PASS
# tampered : FAIL (agent signature invalid)
How it relates
| Implementation | Repo | Role |
|---|---|---|
| TypeScript | agent-toolprint |
Reference. Owns SPEC + conformance vectors. |
| Python | agent-toolprint-py |
Same wire format. Same vectors. |
| Rust | this repo | Same wire format. Same vectors. |
Conformance
# 3 tests, 15 vectors
Vectors under vectors/ are copied from the TS conformance suite. Coverage maps to SPEC §6:
- C1 byte-identical canonical encoding (3 vectors).
- C2 any field mutation fails verify (7 vectors).
- C3 single-signed envelope rejected (2 vectors).
- C4
parent.id == child.parentenforced (3 vectors).
Architecture
See docs/architecture.md.
Development
License
Apache-2.0 — see LICENSE.