A library for ATProtocol identities.
README.md

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🔑...)
  • <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.