Skip to content

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

bash
cargo add kanoniv-agent-auth

Version: 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.

rust
// 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:

FieldTypeDescription
didStringdid:agent:{hex(sha256(pubkey)[..16])}
public_key_bytesVec<u8>Raw 32-byte Ed25519 public key
created_atOption<String>RFC 3339 creation timestamp (skipped in JSON if None)
rust
// 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::Value

ServiceEndpoint

A service endpoint for a DID Document (W3C DID Core specification). Implements Clone, Debug, Serialize, Deserialize, PartialEq, Eq.

Fields:

FieldTypeDescription
idStringFragment ID (e.g. #messaging) or full URI
service_typeStringService type (e.g. AgentMessaging, KanonivResolve)
endpointStringThe endpoint URL
rust
pub fn new(
    id: impl Into<String>,
    service_type: impl Into<String>,
    endpoint: impl Into<String>,
) -> Self

Fragment 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:

FieldTypeDescription
payloadserde_json::ValueThe message payload (arbitrary JSON)
signer_didStringDID of the signer
nonceStringUUID v4 nonce for replay protection
timestampStringRFC 3339 timestamp (milliseconds, Z suffix)
signatureStringHex-encoded Ed25519 signature (128 hex chars)
rust
// 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) -> String

The 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").

VariantPayloadDescription
ActionScope(Vec<String>)List of allowed actionsRestrict to specific actions
ExpiresAt(String)RFC 3339 timestampDelegation expires at this time
MaxCost(f64)Maximum costCost ceiling for delegated operations
Resource(String)Glob patternResource pattern (e.g. entity:customer:*)
Context { key, value }Key-value pairRestrict to a specific context (task_id, session_id)
Custom { key, value }Key + JSON valueArbitrary user-defined constraint

Delegation

A cryptographic delegation of authority from one agent to another. Implements Clone, Debug, Serialize, Deserialize.

Fields:

FieldTypeDescription
issuer_didStringDID of the granting agent
delegate_didStringDID of the receiving agent
issuer_public_keyVec<u8>Issuer's public key (for self-verifying chains)
caveatsVec<Caveat>Constraints on the delegated authority
parent_proofOption<Box<Delegation>>Parent delegation (None for root)
proofSignedMessageCryptographic proof signed by issuer
rust
// 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) -> usize

MAX_CHAIN_DEPTH

rust
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:

FieldTypeDescription
invoker_didStringDID of the agent performing the action
actionStringThe action being performed
argsserde_json::ValueAction arguments / context
delegationDelegationThe delegation chain proving authority
proofSignedMessageSigned by invoker
rust
pub fn create(
    invoker_keypair: &AgentKeyPair,
    action: &str,
    args: serde_json::Value,
    delegation: Delegation,
) -> Result<Self, CryptoError>

VerificationResult

Result of a successful verification.

FieldTypeDescription
invoker_didStringThe invoker's DID
root_didStringThe root authority's DID
chainVec<String>Chain of DIDs from invoker to root
depthusizeChain depth

Free Functions

rust
// 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:

FieldTypeDescription
invocationInvocationThe action + args + delegation chain + signature
invoker_public_keyStringHex-encoded Ed25519 public key (64 chars)
rust
// 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.

VariantBehavior
RequiredReject tool calls without a valid proof
OptionalVerify if present, allow unauthenticated calls
DisabledSkip all proof verification
rust
pub fn from_str_lossy(s: &str) -> Self

Accepts: required/enforce/strict, disabled/off/none, anything else maps to Optional.

McpAuthOutcome

Result of MCP auth verification for a single tool call.

FieldTypeDescription
verifiedOption<VerificationResult>Verification result if proof was present and valid
argsserde_json::ValueTool arguments with _proof stripped

Free Functions

rust
// 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.

VariantSerialized 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:

FieldTypeDescription
agent_didStringDID of the agent that performed the action
actionActionTypeWhat action was performed
entity_idsVec<String>Entity IDs affected
parent_idsVec<String>Parent entry content hashes (for DAG chaining)
metadataserde_json::ValueAdditional context
signed_envelopeSignedMessageThe signed proof
rust
// 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) -> String

Module: error

CryptoError

Error enum for all cryptographic operations. Implements Debug, Display (via thiserror), Error.

VariantDescription
InvalidKeyLength(usize)Expected 32 bytes, got N
InvalidPublicKeyInvalid Ed25519 public key
SignatureInvalidSignature 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:

rust
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;

The identity and delegation layer for AI agents.