Crates.io | atproto-record |
lib.rs | atproto-record |
version | 0.11.2 |
created_at | 2025-05-30 16:58:48.516915+00 |
updated_at | 2025-08-20 18:53:46.693387+00 |
description | AT Protocol record signature operations - cryptographic signing and verification for AT Protocol records |
homepage | https://tangled.sh/@smokesignal.events/atproto-identity-rs |
repository | https://tangled.sh/@smokesignal.events/atproto-identity-rs |
max_upload_size | |
id | 1695391 |
size | 259,656 |
Cryptographic signature operations and utilities for AT Protocol records.
A comprehensive Rust library for working with AT Protocol records, providing cryptographic signature creation and verification, AT-URI parsing, and datetime utilities. Built on IPLD DAG-CBOR serialization with support for P-256, P-384, and K-256 elliptic curve cryptography.
The following command-line tools are available when built with the clap
feature:
atproto-record-sign
: Sign AT Protocol records with private keys, supporting flexible argument orderingatproto-record-verify
: Verify AT Protocol record signatures by validating cryptographic signatures against issuer DIDs and public keysuse atproto_record::signature;
use atproto_identity::key::identify_key;
use serde_json::json;
// Parse the signing key from a did:key
let key_data = identify_key("did:key:zQ3sh...")?;
// The record to sign
let record = json!({"$type": "app.bsky.feed.post", "text": "Hello world!"});
// Signature metadata (issuer is required, other fields are optional)
let signature_object = json!({
"issuer": "did:plc:issuer"
// Optional: "issuedAt", "purpose", "expiry", etc.
});
// Create the signed record with embedded signatures array
let signed_record = signature::create(
&key_data,
&record,
"did:plc:repository",
"app.bsky.feed.post",
signature_object
).await?;
use atproto_record::signature;
use atproto_identity::key::identify_key;
// Parse the public key for verification
let issuer_key = identify_key("did:key:zQ3sh...")?;
// Verify the signature (throws error if invalid)
signature::verify(
"did:plc:issuer", // Expected issuer DID
&issuer_key, // Public key for verification
signed_record, // The signed record
"did:plc:repository", // Repository context
"app.bsky.feed.post" // Collection context
).await?;
use atproto_record::aturi::ATURI;
use std::str::FromStr;
// Parse an AT-URI into its components
let aturi = ATURI::from_str("at://did:plc:abc123/app.bsky.feed.post/3k2k4j5h6g")?;
// Access the parsed components
println!("Authority: {}", aturi.authority); // "did:plc:abc123"
println!("Collection: {}", aturi.collection); // "app.bsky.feed.post"
println!("Record Key: {}", aturi.record_key); // "3k2k4j5h6g"
// The Display trait formats back to a valid AT-URI
println!("Full URI: {}", aturi); // "at://did:plc:abc123/app.bsky.feed.post/3k2k4j5h6g"
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
// Use the datetime module for consistent RFC 3339 formatting
#[derive(Serialize, Deserialize)]
struct Record {
#[serde(with = "atproto_record::datetime::format")]
created_at: DateTime<Utc>,
#[serde(with = "atproto_record::datetime::optional_format")]
updated_at: Option<DateTime<Utc>>,
}
All CLI tools require the clap
feature:
# Build with CLI support
cargo build --features clap --bins
# Sign a record
cargo run --features clap --bin atproto-record-sign -- \
did:key:zQ3sh... # Signing key (did:key format)
did:plc:issuer # Issuer DID
record.json # Record file (or use -- for stdin)
repository=did:plc:repo # Repository context
collection=app.bsky.feed.post # Collection type
# Sign with custom fields (e.g., issuedAt, purpose, expiry)
cargo run --features clap --bin atproto-record-sign -- \
did:key:zQ3sh... did:plc:issuer record.json \
repository=did:plc:repo collection=app.bsky.feed.post \
issuedAt="2024-01-01T00:00:00.000Z" purpose="attestation"
# Verify a signature
cargo run --features clap --bin atproto-record-verify -- \
did:plc:issuer # Expected issuer DID
did:key:zQ3sh... # Verification key
signed.json # Signed record file
repository=did:plc:repo # Repository context (must match signing)
collection=app.bsky.feed.post # Collection type (must match signing)
# Read from stdin
echo '{"text":"Hello"}' | cargo run --features clap --bin atproto-record-sign -- \
did:key:zQ3sh... did:plc:issuer -- \
repository=did:plc:repo collection=app.bsky.feed.post
MIT License