webbotauth.dev KMS

Ed25519 Key Management Service for Cloudflare Workers.

Generate Ed25519 signing keys and sign data remotely. Private keys never leave the KMS. Supports two key distribution standards:

Get Started

Create a customer account to get your API key and subdomain:

# Or via API:
curl -X POST https://webbotauth.dev/admin/customers \
  -H "Content-Type: application/json" \
  -d '{"name": "My Bot Agent"}'

Use Case 1: OAuth/OIDC JWT Signing

Sign JWTs for OAuth 2.0 client authentication (private_key_jwt):

// Your agent's subdomain exposes:
// https://<uuid>.webbotauth.dev/.well-known/jwks.json
// https://<uuid>.webbotauth.dev/client-metadata.json

// Sign a JWT using KMSSubtleCrypto
const jwt = await issueJwt(kms, key, {
  iss: "https://<uuid>.webbotauth.dev/client-metadata.json",
  sub: "https://<uuid>.webbotauth.dev/client-metadata.json",
  aud: "https://auth-server.example.com",
});

Use Case 2: Web Bot Auth (HTTP Message Signatures)

Authenticate automated HTTP traffic per draft-meunier-web-bot-auth-architecture:

// Your agent's directory is at:
// https://<uuid>.webbotauth.dev/.well-known/http-message-signatures-directory

// When making requests, include Signature-Agent header:
Signature-Agent: sig1="https://<uuid>.webbotauth.dev"

// Sign requests per RFC 9421 with tag="web-bot-auth"
Signature-Input: sig1=("@authority");created=...;keyid="...";tag="web-bot-auth"
Signature: sig1=:base64-signature:=

The directory endpoint is signed per draft-meunier-http-message-signatures-directory Section 5.2.

API Endpoints

KMSSubtleCrypto Client

import { KMSSubtleCrypto } from "@webbotauth/kms-core";

const kms = new KMSSubtleCrypto({
  apiKey: env.KMS_API_KEY,
  fetcher: env.KMS.fetch.bind(env.KMS), // Service binding
});

// Generate key - private key stays in KMS
const keyPair = await kms.generateKey("Ed25519", true, ["sign"]);

// Sign data - WebCrypto-like API
const signature = await kms.sign(
  "Ed25519",
  keyPair.privateKey,
  new TextEncoder().encode("data to sign")
);

Service Binding Setup

// wrangler.jsonc
{
  "services": [{ "binding": "KMS", "service": "kms-worker" }]
}

// Then: wrangler secret put KMS_API_KEY

Specs