Secure storage and distribution of cryptographic keys in ATProto applications
README.md

@atpkeyserver/client Examples#

This directory contains examples demonstrating how to use the ATP Keyserver client library.

Available Examples#

basic-usage.ts#

A comprehensive example showing all major features of the library:

  1. Crypto Functions Only - Direct encrypt/decrypt without keyserver
  2. KeyserverClient Encryption - Full flow with service auth
  3. KeyserverClient Decryption - Retrieving and decrypting content
  4. Error Handling - Proper error handling for all error types
  5. Cache Management - Understanding and managing the cache
  6. Batch Decryption - Processing multiple encrypted posts efficiently

Prerequisites#

Node.js#

Requires Node.js 22+ or Bun:

node --version  # Should be v22.0.0 or higher

Dependencies#

The example requires these packages:

# In the client directory
cd packages/client

# Install dependencies
bun install  # or npm install

Required packages:

  • @atpkeyserver/client (this library)
  • @atproto/api (for PDS integration)

Running the Example#

bun run examples/basic-usage.ts

Using Node.js#

First, build the library:

npm run build

Then run with tsx or ts-node:

npx tsx examples/basic-usage.ts

Expected Output#

The example will run through all 6 examples sequentially, demonstrating:

  • ✅ Successful crypto operations
  • ⚠️ Expected failures in mock environment (keyserver not running)
  • 📖 Educational comments about each operation
  • 🎨 Colored output showing success/error states

Note: Examples 2-6 use mock data and will show expected errors since no actual keyserver is running. This is intentional and demonstrates error handling.

Adapting for Production#

To use in production, replace mock values with real ones:

1. Authenticate with PDS#

const agent = new AtpAgent({ service: 'https://bsky.social' })
await agent.login({
  identifier: 'your-handle.bsky.social',
  password: 'your-app-password'
})

2. Use Real Keyserver#

const keyserver = new KeyserverClient({
  keyserverDid: 'did:web:your-keyserver.com',  // Real keyserver DID
  getServiceAuthToken: async (aud, lxm) => {
    const { data } = await agent.com.atproto.server.getServiceAuth({
      aud,
      lxm,
      exp: Math.floor(Date.now() / 1000) + 60
    })
    return data.token
  }
})

3. Store/Retrieve Real Posts#

Replace mock data with actual PDS operations:

// Create encrypted post
const record = await agent.com.atproto.repo.putRecord({
  repo: agent.session.did,
  collection: 'app.bsky.feed.post',
  record: {
    encrypted_content: ciphertext,
    key_version: version,
    encrypted_at: new Date().toISOString(),
    visibility: 'followers'
  }
})

// Retrieve and decrypt
const post = await agent.getPost(postUri)
const plaintext = await keyserver.decrypt(
  postUri,
  groupId,
  post.encrypted_content,
  post.key_version
)

Understanding the Output#

Successful Operations#

✅ Crypto round-trip successful!
✅ Encrypted successfully!

These indicate operations completed without errors.

Expected Errors (Mock Environment)#

❌ Decryption failed (expected in mock environment)

Since no real keyserver is running, these errors are expected and demonstrate proper error handling.

Error Types Demonstrated#

The examples show how to handle:

  • 🚫 ForbiddenError - User lost access
  • 🔍 NotFoundError - Resource deleted
  • 🔐 DecryptionError - Cannot decrypt (permanent)
  • 🌐 NetworkError - Temporary network issue (can retry)

Common Issues#

Import Errors#

If you see module resolution errors:

# Ensure library is built
bun run build

# Check TypeScript paths are correct
cat tsconfig.json

Runtime Errors#

If crypto operations fail:

  • Ensure Node.js 22+ (native crypto support)
  • Check that @noble/ciphers is installed
  • Verify hex-encoded keys are exactly 64 characters

Next Steps#

After understanding the examples:

  1. Read ../README.md for complete API reference
  2. Review ../../docs/ENCRYPTION_PROTOCOL.md for protocol details
  3. Check ../../docs/SECURITY.md for security best practices
  4. Build your application using the patterns demonstrated

Questions?#