atproto-record 0.3.0

AT Protocol record signature operations - cryptographic signing and verification for AT Protocol records
Documentation

atproto-record

A Rust library for AT Protocol record signature operations, providing cryptographic signing and verification capabilities for AT Protocol records.

Overview

This crate provides functionality for:

  • Record Signing: Create cryptographic signatures for AT Protocol records
  • Signature Verification: Verify existing signatures against records and public keys
  • Error Handling: Structured error types for signature operations
  • Multi-curve Support: Support for P-256 and K-256 elliptic curves via atproto-identity

Features

  • Create signatures for AT Protocol records with proper $sig object handling
  • Required signature object validation (must include issuer and issued_at fields)
  • Verify record signatures against issuer public keys
  • IPLD DAG-CBOR serialization for consistent signature generation
  • Multibase encoding for signature representation
  • Integration with atproto-identity for cryptographic key operations
  • Repository and collection context support in signature objects
  • Comprehensive error handling with structured error types including creation and verification errors

Usage

Creating Signatures

use atproto_record::signature;
use atproto_identity::key::{identify_key, KeyType};
use serde_json::json;
use atproto_record::errors::VerificationError;

# async fn example() -> Result<(), VerificationError> {
// Prepare key data
let key_data = identify_key("did:key:example...").map_err(|e| {
    VerificationError::KeyOperationFailed(e)
})?;

// Create a record to sign
let record = json!({
    "$type": "app.bsky.feed.post",
    "text": "Hello AT Protocol!",
    "createdAt": "2024-01-01T00:00:00Z"
});

// Create signature object with required fields
let signature_object = json!({
    "issuer": "did:plc:signer123",
    "issued_at": "2024-01-01T00:00:00Z"
});

// Create signature
let signed_record = signature::create(
    &key_data,
    &record,
    "did:plc:user123",
    "app.bsky.feed.post",
    signature_object
).await?;
# Ok(())
# }

Verifying Signatures

use atproto_record::signature;
use atproto_identity::key::identify_key;
use atproto_record::errors::VerificationError;

# async fn example() -> Result<(), VerificationError> {
// Get the issuer's public key
let issuer_key = identify_key("did:key:issuer...").map_err(|e| {
    VerificationError::KeyOperationFailed(e)
})?;

// Verify the signature
signature::verify(
    "did:plc:issuer123",
    &issuer_key,
    signed_record,
    "did:plc:user123",
    "app.bsky.feed.post"
).await?;
# Ok(())
# }

Modules

  • [signature] - Core signature creation and verification functions
  • [errors] - Structured error types for signature operations

Error Handling

The crate uses structured error types defined in the errors module:

use atproto_record::errors::VerificationError;
use serde_json::json;

// Example error handling for signature creation
let signature_object = json!({ "missing": "required_fields" });

match signature::create(&key_data, &record, "repo", "collection", signature_object).await {
    Ok(signed_record) => println!("Signature created successfully!"),
    Err(VerificationError::SignatureObjectMissingField { field }) => {
        println!("Missing required field in signature object: {}", field);
    }
    Err(VerificationError::InvalidSignatureObjectType) => {
        println!("Signature object must be a JSON object");
    }
    Err(VerificationError::KeyOperationFailed(e)) => {
        println!("Cryptographic operation failed: {}", e);
    }
    Err(e) => println!("Other error: {}", e),
}

// Example error handling for signature verification
match signature::verify("did:plc:issuer", &key_data, record, "repo", "collection").await {
    Ok(()) => println!("Signature valid!"),
    Err(VerificationError::NoValidSignatureForIssuer { issuer }) => {
        println!("No valid signature found for issuer: {}", issuer);
    }
    Err(VerificationError::NoSignaturesField) => {
        println!("Record contains no signatures field");
    }
    Err(e) => println!("Verification failed: {}", e),
}

Dependencies

This crate builds on:

  • atproto-identity - Cryptographic key operations and DID resolution
  • serde_ipld_dagcbor - IPLD DAG-CBOR serialization for signature content
  • multibase - Base encoding for signature representation
  • serde_json - JSON handling for AT Protocol records
  • anyhow - Error handling utilities
  • thiserror - Structured error type derivation

License

Licensed under the MIT License.