atproto-identity 0.6.0

AT Protocol identity management - DID resolution, handle resolution, and cryptographic operations
Documentation

atproto-identity

A Rust library for AT Protocol identity resolution and management.

Overview

atproto-identity provides comprehensive support for resolving and managing identities in the AT Protocol ecosystem. This library handles multiple DID (Decentralized Identifier) methods including did:plc and did:web, as well as AT Protocol handle resolution via both DNS and HTTP methods.

This project was extracted from the open-sourced Smokesignal project and is designed to be a standalone, reusable library for AT Protocol identity operations.

Features

  • Handle Resolution: Resolve AT Protocol handles to DIDs using DNS TXT records and HTTP well-known endpoints
  • DID Document Retrieval: Fetch and parse DID documents for did:plc and did:web identifiers
  • Multiple Resolution Methods: Supports both DNS and HTTP-based handle resolution with conflict detection
  • Configurable DNS: Custom DNS nameserver support with fallback to system defaults
  • Cryptographic Key Operations: Support for P-256 and K-256 key identification, signature validation, and signing
  • Structured Logging: Built-in tracing support for debugging and monitoring
  • Type Safety: Comprehensive error handling with structured error types

Supported DID Methods

  • did-method-plc: Public Ledger of Credentials DIDs via PLC directory
  • did-method-web: Web-based DIDs following the did:web specification with URL conversion utilities
  • ATProtocol Handle Resolution: AT Protocol handles (e.g., ngerakines.me) can be resolved to DIDs

Installation

Add this to your Cargo.toml:

[dependencies]
atproto-identity = "0.6.0"

Usage

Basic Handle Resolution

use atproto_identity::resolve::{resolve_subject, create_resolver};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let http_client = reqwest::Client::new();
    let dns_resolver = create_resolver(&[]);
    
    let did = resolve_subject(&http_client, &dns_resolver, "ngerakines.me").await?;
    println!("Resolved DID: {}", did);
    
    Ok(())
}

DID Document Retrieval

use atproto_identity::{plc, web};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let http_client = reqwest::Client::new();
    
    // Query PLC DID document
    let plc_doc = plc::query(&http_client, "plc.directory", "did:plc:example123").await?;
    
    // Query Web DID document
    let web_doc = web::query(&http_client, "did:web:example.com").await?;
    
    // Convert Web DID to URL (for custom processing)
    let did_url = web::did_web_to_url("did:web:example.com")?;
    println!("DID document URL: {}", did_url);
    
    Ok(())
}

Web DID URL Conversion

The web module provides utilities for converting DID identifiers to their HTTPS document URLs:

use atproto_identity::web;

fn main() -> anyhow::Result<()> {
    // Convert simple hostname DID
    let url = web::did_web_to_url("did:web:example.com")?;
    // Returns: "https://example.com/.well-known/did.json"
    
    // Convert DID with path components  
    let url = web::did_web_to_url("did:web:example.com:path:subpath")?;
    // Returns: "https://example.com/path/subpath/did.json"
    
    Ok(())
}

Cryptographic Key Operations

The key module provides utilities for working with cryptographic keys:

use atproto_identity::key::{identify_key, validate, KeyType};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Identify a key from a DID key string
    let key_data = identify_key("did:key:zQ3shNzMp4oaaQ1gQRzCxMGXFrSW3NEM1M9T6KCY9eA7HhyEA")?;
    
    match key_data.0 {
        KeyType::K256Public => println!("K-256 public key"),
        KeyType::P256Public => println!("P-256 public key"),
        KeyType::K256Private => println!("K-256 private key"),
        KeyType::P256Private => println!("P-256 private key"),
    }
    
    // Validate a signature (example with dummy data)
    let content = b"hello world";
    let signature = vec![0u8; 64]; // Replace with actual signature
    validate(&key_data, &signature, content)?;
    
    Ok(())
}

Configuration

The library supports various configuration options through environment variables:

# Custom PLC directory hostname
export PLC_HOSTNAME=plc.directory

# Custom DNS nameservers (semicolon-separated)
export DNS_NAMESERVERS=8.8.8.8;1.1.1.1

# Custom CA certificate bundles (semicolon-separated paths)
export CERTIFICATE_BUNDLES=/path/to/cert1.pem;/path/to/cert2.pem

# Custom User-Agent string
export USER_AGENT="my-app/1.0"

Command Line Tools

The library includes four command-line tools for AT Protocol identity operations:

atproto-identity-resolve

Resolves AT Protocol handles and DIDs to their canonical DID identifiers and optionally retrieves full DID documents. This tool supports both did:plc and did:web methods with configurable DNS and HTTP settings for comprehensive identity resolution.

Features:

  • Handle Resolution: Converts AT Protocol handles (e.g., alice.bsky.social) to DIDs
  • DID Document Retrieval: Fetches complete DID documents with verification methods
  • Multi-Method Support: Handles both PLC directory and Web DID resolution
  • DNS Configuration: Supports custom DNS nameservers and certificate bundles
  • Output Options: Choose between DID-only output or full document retrieval
# Resolve a handle to its DID
cargo run --bin atproto-identity-resolve alice.bsky.social

# Resolve a DID and get full DID document
cargo run --bin atproto-identity-resolve --did-document did:plc:user123

# Resolve with custom configuration
PLC_HOSTNAME=plc.directory DNS_NAMESERVERS="8.8.8.8;1.1.1.1" \
  cargo run --bin atproto-identity-resolve --did-document alice.bsky.social

atproto-identity-sign

Creates cryptographic signatures of JSON data using AT Protocol DID keys. This tool reads JSON files, serializes them using IPLD DAG-CBOR format for consistency, and produces multibase-encoded signatures suitable for AT Protocol operations.

Features:

  • DID Key Support: Works with both P-256 and K-256 private keys
  • JSON Processing: Handles arbitrary JSON data structures
  • IPLD Serialization: Uses DAG-CBOR for deterministic serialization
  • Multibase Output: Produces signatures in multibase format
  • File Input: Reads JSON data from specified files
# Sign a JSON file with a DID private key
cargo run --bin atproto-identity-sign did:key:zQ3shNzMp4oaaQ1... data.json

# Example output: multibase-encoded signature string
# uEiB5vJz8aZhpx3bY2nKfRzPpLmQwA8Z9qXhNvYtF2gH7...

atproto-identity-validate

Verifies cryptographic signatures of JSON data using AT Protocol DID keys. This tool validates that signatures were created by the holder of a specific private key, ensuring data integrity and authenticity for AT Protocol operations.

Features:

  • Signature Verification: Validates multibase-encoded signatures
  • DID Key Support: Works with P-256 and K-256 public keys
  • IPLD Deserialization: Uses DAG-CBOR for consistent verification
  • File Processing: Reads JSON data and signatures from files
  • Exit Code Reporting: Returns appropriate exit codes for success/failure
# Validate a signature against a JSON file
cargo run --bin atproto-identity-validate did:key:zQ3shNzMp4oaaQ1... data.json uEiB5vJz8aZ...

# Successful validation returns exit code 0
# Failed validation returns exit code 1

Arguments:

  • <public_key> - DID key string for verification (did:key:...)
  • <data_file> - JSON file containing the original data
  • <signature> - Multibase-encoded signature to verify

atproto-identity-key

Provides comprehensive cryptographic key management capabilities for AT Protocol operations, including key generation and inspection for both P-256 and K-256 elliptic curves.

Features:

  • Key Generation: Creates new private keys for both curve types
  • Secure Random: Uses cryptographically secure random number generation
  • DID Key Format: Outputs keys in standard DID key format
  • Multiple Algorithms: Supports both P-256 (secp256r1) and K-256 (secp256k1) curves
  • Development Ready: Generated keys ready for use in AT Protocol operations
# Generate a new P-256 private key (recommended for most AT Protocol use)
cargo run --bin atproto-identity-key generate p256

# Generate a new K-256 private key (Bitcoin-style curve)
cargo run --bin atproto-identity-key generate k256

# Example output format:
# did:key:zQ3shNzMp4oaaQ1gQRzCxMGXFrSW3NEM1M9T6KCY9eA7HhyEA

Key Types:

  • P-256: NIST P-256 curve (secp256r1) - Recommended for new applications
  • K-256: secp256k1 curve (same as Bitcoin) - For Bitcoin-compatible operations

Security Note: Generated keys are output to stdout and should be stored securely. Never commit private keys to version control or share them publicly.

Architecture

The library is organized into several modules:

  • resolve: Core resolution logic for handles and DIDs
  • plc: PLC directory client for did:plc resolution
  • web: Web DID client for did:web resolution and URL conversion
  • model: Data structures for DID documents and AT Protocol entities
  • validation: Input validation for handles and DIDs
  • config: Configuration management and environment variable handling
  • errors: Structured error types following project conventions
  • key: Cryptographic key operations including signature validation and key identification for P-256 and K-256 curves

Error Handling

All errors follow a structured format:

error-atproto-identity-<domain>-<number> <message>: <details>

Examples:

  • error-atproto-identity-resolve-1 Multiple DIDs resolved for method
  • error-atproto-identity-plc-1 HTTP request failed: https://plc.directory/did:plc:example Not Found
  • error-did-web-1 Invalid DID format: missing 'did:web:' prefix

Contributing

Contributions are welcome! Please ensure that:

  1. All tests pass: cargo test
  2. Code is properly formatted: cargo fmt
  3. No linting issues: cargo clippy
  4. New functionality includes appropriate tests

License

This project is licensed under the MIT License. See the LICENSE file for details.

Acknowledgments

This library was extracted from the Smokesignal project, an open-source event and RSVP management and discovery application.