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:plcanddid:webidentifiers - 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.5.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:plcresolution - web: Web DID client for
did:webresolution 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 methoderror-atproto-identity-plc-1 HTTP request failed: https://plc.directory/did:plc:example Not Founderror-did-web-1 Invalid DID format: missing 'did:web:' prefix
Contributing#
Contributions are welcome! Please ensure that:
- All tests pass:
cargo test - Code is properly formatted:
cargo fmt - No linting issues:
cargo clippy - 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.