Rust SDK - kanoniv-agent-auth
Cryptographic identity and delegation for AI agents. Ed25519 keypairs, did:agent: decentralized identifiers, signed message envelopes, attenuated delegation chains, MCP authentication middleware, and provenance audit entries.
Installation
cargo add kanoniv-agent-authVersion: 0.2.0 | MSRV: Rust 2021 edition | License: MIT
docs.rs/kanoniv-agent-auth | crates.io/crates/kanoniv-agent-auth
Dependencies
The crate pulls in ed25519-dalek, sha2, serde, serde_json, chrono, uuid, hex, bs58, and thiserror. No optional features or feature flags.
Module: identity
Agent cryptographic identity - Ed25519 keypairs and did:agent: identifiers.
AgentKeyPair
An agent's Ed25519 keypair used for signing messages and proving identity. The secret key is 32 bytes. Not Clone or Serialize by design - secret keys should not be copied casually.
// Generate a new random keypair
pub fn generate() -> Self
// Reconstruct from 32-byte secret key (sets created_at to now)
pub fn from_bytes(secret: &[u8; 32]) -> Self
// Reconstruct with a known creation time
pub fn from_bytes_with_created_at(
secret: &[u8; 32],
created_at: chrono::DateTime<chrono::Utc>,
) -> Self
// Export the 32-byte secret key for persistence
pub fn secret_bytes(&self) -> [u8; 32]
// Derive the public identity
pub fn identity(&self) -> AgentIdentity
// Get the key creation timestamp
pub fn created_at(&self) -> &chrono::DateTime<chrono::Utc>AgentIdentity
Public identity derived from a keypair - safe to share and store. Implements Clone, Debug, Serialize, Deserialize, PartialEq, Eq.
Fields:
| Field | Type | Description |
|---|---|---|
did | String | did:agent:{hex(sha256(pubkey)[..16])} |
public_key_bytes | Vec<u8> | Raw 32-byte Ed25519 public key |
created_at | Option<String> | RFC 3339 creation timestamp (skipped in JSON if None) |
// Create from a public verifying key (no creation timestamp)
pub fn from_public_key(key: &VerifyingKey) -> Self
// Create with optional creation timestamp
pub fn from_public_key_with_created_at(
key: &VerifyingKey,
created_at: Option<String>,
) -> Self
// Reconstruct from raw 32-byte public key (no timestamp)
pub fn from_bytes(bytes: &[u8]) -> Result<Self, CryptoError>
// Decode from multibase-encoded Ed25519 key (z{base58btc(0xed01 + key)})
pub fn from_multibase(multibase: &str) -> Result<Self, CryptoError>
// Get the Ed25519 verifying key for signature verification
pub fn verifying_key(&self) -> Result<VerifyingKey, CryptoError>
// Generate a W3C DID Document (no services)
pub fn did_document(&self) -> serde_json::Value
// Generate a W3C DID Document with service endpoints
pub fn did_document_with_services(
&self,
services: &[ServiceEndpoint],
) -> serde_json::ValueServiceEndpoint
A service endpoint for a DID Document (W3C DID Core specification). Implements Clone, Debug, Serialize, Deserialize, PartialEq, Eq.
Fields:
| Field | Type | Description |
|---|---|---|
id | String | Fragment ID (e.g. #messaging) or full URI |
service_type | String | Service type (e.g. AgentMessaging, KanonivResolve) |
endpoint | String | The endpoint URL |
pub fn new(
id: impl Into<String>,
service_type: impl Into<String>,
endpoint: impl Into<String>,
) -> SelfFragment IDs starting with # are auto-prefixed with the DID in did_document_with_services.
Module: signing
Signed message envelopes with Ed25519 signatures.
SignedMessage
A cryptographically signed message envelope. Implements Clone, Debug, Serialize, Deserialize.
Fields:
| Field | Type | Description |
|---|---|---|
payload | serde_json::Value | The message payload (arbitrary JSON) |
signer_did | String | DID of the signer |
nonce | String | UUID v4 nonce for replay protection |
timestamp | String | RFC 3339 timestamp (milliseconds, Z suffix) |
signature | String | Hex-encoded Ed25519 signature (128 hex chars) |
// Sign a payload with the given keypair
pub fn sign(
keypair: &AgentKeyPair,
payload: serde_json::Value,
) -> Result<Self, CryptoError>
// Verify against a known public identity
pub fn verify(&self, identity: &AgentIdentity) -> Result<(), CryptoError>
// Compute SHA-256 content hash (canonical field ordering)
pub fn content_hash(&self) -> StringThe canonical form for signing uses alphabetically sorted top-level keys: {nonce, payload, signer_did, timestamp}. The content hash also uses alphabetical ordering: {nonce, payload, signature, signer_did, timestamp}. This ensures cross-language determinism.
Module: delegation
Cryptographic delegation with attenuated capabilities. Implements Macaroon-style delegation where agents grant subsets of their authority with constraints.
Caveat
A constraint on delegated authority. Implements Clone, Debug, Serialize, Deserialize, PartialEq. Tagged enum with serde(tag = "type", content = "value").
| Variant | Payload | Description |
|---|---|---|
ActionScope(Vec<String>) | List of allowed actions | Restrict to specific actions |
ExpiresAt(String) | RFC 3339 timestamp | Delegation expires at this time |
MaxCost(f64) | Maximum cost | Cost ceiling for delegated operations |
Resource(String) | Glob pattern | Resource pattern (e.g. entity:customer:*) |
Context { key, value } | Key-value pair | Restrict to a specific context (task_id, session_id) |
Custom { key, value } | Key + JSON value | Arbitrary user-defined constraint |
Delegation
A cryptographic delegation of authority from one agent to another. Implements Clone, Debug, Serialize, Deserialize.
Fields:
| Field | Type | Description |
|---|---|---|
issuer_did | String | DID of the granting agent |
delegate_did | String | DID of the receiving agent |
issuer_public_key | Vec<u8> | Issuer's public key (for self-verifying chains) |
caveats | Vec<Caveat> | Constraints on the delegated authority |
parent_proof | Option<Box<Delegation>> | Parent delegation (None for root) |
proof | SignedMessage | Cryptographic proof signed by issuer |
// Create a root delegation (issuer is root authority)
pub fn create_root(
issuer_keypair: &AgentKeyPair,
delegate_did: &str,
caveats: Vec<Caveat>,
) -> Result<Self, CryptoError>
// Create a delegated delegation (with parent chain)
// Caveats accumulate - can only narrow, never widen
pub fn delegate(
issuer_keypair: &AgentKeyPair,
delegate_did: &str,
additional_caveats: Vec<Caveat>,
parent: Delegation,
) -> Result<Self, CryptoError>
// Get chain depth (0 for root, 1 for first delegation, etc.)
pub fn depth(&self) -> usizeMAX_CHAIN_DEPTH
pub const MAX_CHAIN_DEPTH: usize = 32;Maximum delegation chain depth to prevent DoS via deeply nested chains.
Invocation
An agent exercising delegated authority. Implements Clone, Debug, Serialize, Deserialize.
Fields:
| Field | Type | Description |
|---|---|---|
invoker_did | String | DID of the agent performing the action |
action | String | The action being performed |
args | serde_json::Value | Action arguments / context |
delegation | Delegation | The delegation chain proving authority |
proof | SignedMessage | Signed by invoker |
pub fn create(
invoker_keypair: &AgentKeyPair,
action: &str,
args: serde_json::Value,
delegation: Delegation,
) -> Result<Self, CryptoError>VerificationResult
Result of a successful verification.
| Field | Type | Description |
|---|---|---|
invoker_did | String | The invoker's DID |
root_did | String | The root authority's DID |
chain | Vec<String> | Chain of DIDs from invoker to root |
depth | usize | Chain depth |
Free Functions
// Verify an invocation's full authority chain (no revocation check)
pub fn verify_invocation(
invocation: &Invocation,
invoker_identity: &AgentIdentity,
root_identity: &AgentIdentity,
) -> Result<VerificationResult, CryptoError>
// Verify with revocation callback
pub fn verify_invocation_with_revocation(
invocation: &Invocation,
invoker_identity: &AgentIdentity,
root_identity: &AgentIdentity,
is_revoked: impl Fn(&str) -> bool,
) -> Result<VerificationResult, CryptoError>
// Verify a delegation chain without an invocation
pub fn verify_delegation_chain(
delegation: &Delegation,
root_identity: &AgentIdentity,
) -> Result<Vec<String>, CryptoError>
// Verify a delegation chain with revocation check
pub fn verify_delegation_chain_with_revocation(
delegation: &Delegation,
root_identity: &AgentIdentity,
is_revoked: impl Fn(&str) -> bool,
) -> Result<Vec<String>, CryptoError>Module: mcp
MCP (Model Context Protocol) authentication middleware. Agents attach a _proof field to tool arguments containing a self-contained invocation proof.
McpProof
A self-contained invocation proof for MCP transport. Contains everything an MCP server needs to verify the agent's identity and authority without any external key resolver. Implements Clone, Debug, Serialize, Deserialize.
Fields:
| Field | Type | Description |
|---|---|---|
invocation | Invocation | The action + args + delegation chain + signature |
invoker_public_key | String | Hex-encoded Ed25519 public key (64 chars) |
// Create an MCP proof for a tool call
pub fn create(
invoker_keypair: &AgentKeyPair,
action: &str,
args: serde_json::Value,
delegation: Delegation,
) -> Result<Self, CryptoError>
// Extract proof from tool arguments (returns (proof, clean_args))
pub fn extract(
args: &serde_json::Value,
) -> (Option<Self>, serde_json::Value)
// Inject proof into tool arguments (adds _proof field)
pub fn inject(&self, args: &mut serde_json::Value)McpAuthMode
MCP auth mode for server configuration. Implements Copy, Clone, Debug, PartialEq, Eq.
| Variant | Behavior |
|---|---|
Required | Reject tool calls without a valid proof |
Optional | Verify if present, allow unauthenticated calls |
Disabled | Skip all proof verification |
pub fn from_str_lossy(s: &str) -> SelfAccepts: required/enforce/strict, disabled/off/none, anything else maps to Optional.
McpAuthOutcome
Result of MCP auth verification for a single tool call.
| Field | Type | Description |
|---|---|---|
verified | Option<VerificationResult> | Verification result if proof was present and valid |
args | serde_json::Value | Tool arguments with _proof stripped |
Free Functions
// Verify an MCP proof against a root authority
pub fn verify_mcp_call(
proof: &McpProof,
root_identity: &AgentIdentity,
) -> Result<VerificationResult, CryptoError>
// Verify with revocation callback
pub fn verify_mcp_call_with_revocation(
proof: &McpProof,
root_identity: &AgentIdentity,
is_revoked: impl Fn(&str) -> bool,
) -> Result<VerificationResult, CryptoError>
// All-in-one MCP tool call verification
pub fn verify_mcp_tool_call(
tool_name: &str,
args: &serde_json::Value,
root_identity: &AgentIdentity,
mode: McpAuthMode,
) -> Result<McpAuthOutcome, CryptoError>
// All-in-one with revocation support
pub fn verify_mcp_tool_call_with_revocation(
tool_name: &str,
args: &serde_json::Value,
root_identity: &AgentIdentity,
mode: McpAuthMode,
is_revoked: impl Fn(&str) -> bool,
) -> Result<McpAuthOutcome, CryptoError>Module: provenance
Signed audit trail for agent actions. Each entry records what an agent did, with a cryptographic signature proving authorship.
ActionType
The type of action recorded in a provenance entry. Implements Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Display. Serialized as snake_case strings.
| Variant | Serialized as |
|---|---|
Resolve | "resolve" |
Merge | "merge" |
Split | "split" |
Mutate | "mutate" |
Ingest | "ingest" |
Delegate | "delegate" |
Revoke | "revoke" |
Custom(String) | {"custom": "name"} |
ProvenanceEntry
A signed provenance entry in the audit chain. Implements Clone, Debug, Serialize, Deserialize.
Fields:
| Field | Type | Description |
|---|---|---|
agent_did | String | DID of the agent that performed the action |
action | ActionType | What action was performed |
entity_ids | Vec<String> | Entity IDs affected |
parent_ids | Vec<String> | Parent entry content hashes (for DAG chaining) |
metadata | serde_json::Value | Additional context |
signed_envelope | SignedMessage | The signed proof |
// Create and sign a new provenance entry
pub fn create(
keypair: &AgentKeyPair,
action: ActionType,
entity_ids: Vec<String>,
parent_ids: Vec<String>,
metadata: serde_json::Value,
) -> Result<Self, CryptoError>
// Verify signature AND outer field integrity
pub fn verify(
&self,
identity: &AgentIdentity,
) -> Result<(), CryptoError>
// Verify signature only (skip integrity check)
pub fn verify_signature_only(
&self,
identity: &AgentIdentity,
) -> Result<(), CryptoError>
// Get content hash (SHA-256, usable as parent_id)
pub fn content_hash(&self) -> StringModule: error
CryptoError
Error enum for all cryptographic operations. Implements Debug, Display (via thiserror), Error.
| Variant | Description |
|---|---|
InvalidKeyLength(usize) | Expected 32 bytes, got N |
InvalidPublicKey | Invalid Ed25519 public key |
SignatureInvalid | Signature verification failed |
InvalidSignatureEncoding(String) | Bad hex or wrong byte count |
SerializationError(String) | JSON serialization failure |
IntegrityMismatch(String) | Outer field does not match signed payload |
DelegationChainBroken(String) | Chain linkage or depth error |
CaveatViolation(String) | Caveat constraint not satisfied |
DelegationRevoked(String) | Delegation has been revoked |
Re-exports
The crate root re-exports the most commonly used types:
pub use delegation::{
verify_delegation_chain, verify_delegation_chain_with_revocation,
verify_invocation, verify_invocation_with_revocation,
Caveat, Delegation, Invocation, VerificationResult, MAX_CHAIN_DEPTH,
};
pub use error::CryptoError;
pub use identity::{AgentIdentity, AgentKeyPair, ServiceEndpoint};
pub use mcp::{McpAuthMode, McpAuthOutcome, McpProof};
pub use provenance::{ActionType, ProvenanceEntry};
pub use signing::SignedMessage;