Registry Service

The Registry is the cryptographic root of trust in DeadLetter.
It does not store messages. Its sole responsibility is to bind human‑readable handles to encryption public keys and to sign those bindings using a long‑lived root signing key.

All clients (CLI + ESP32 firmware) trust the registry only via its root public key fingerprint.


Responsibilities

The registry provides three core guarantees:

  1. Handle ownership

    • A handle (e.g. alice) is bound to exactly one encryption public key.
    • Only the holder of the corresponding signing key may update or revoke it.
  2. Certificate issuance

    • The registry signs a canonical certificate object:
    {
      "handle": "alice",
      "encPub": "<base64-x25519-public-key>",
      "keyId": "v1",
      "expiresAt": 1735689600
    }
    
  3. Trust anchor distribution

    • The root signing public key is distributed through /keys/
    • Clients verify all certificates using this root key.

Endpoints

MethodPathDescription
GET/keys/Returns the current root signing public key
GET/keys/:handleReturns signed certificate for a handle
POST/registerRegister or rotate a handle certificate
POST/challengeRequest registration challenge
POST/verifyVerify signed challenge response

Root Key Endpoint

GET /keys/

Example response:

{
  "root_pub_b64": "MCowBQYDK2VwAyEA7qZ9...",
  "algorithm": "ed25519",
  "issued_at": 1735611120
}

Clients store the fingerprint of this key locally and warn if it ever changes.


Certificate Fetch

GET /keys/alice

Example:

{
  "cert": {
    "handle": "alice",
    "encPub": "YzN4...",
    "keyId": "v1",
    "expiresAt": 1735689600
  },
  "sig": "b64-ed25519-signature"
}

The CLI verifies:

SHA256( canonical(cert) ) verified by root public key

Registration Flow

  1. Client requests a challenge
  2. Registry returns a random nonce
  3. Client signs nonce using their signing key
  4. Registry verifies and stores the new certificate
  5. Registry persists to registry.store.json

This prevents unauthorized handle hijacking.


Local Persistence

The registry stores all handle mappings in:

dl/packages/registry/registry.store.json

The file is loaded at startup and written atomically after each update.


Security Properties

ThreatMitigation
MITM during registrationChallenge‑response signing
Registry database tamperingRoot‑signed certificates invalidate forged entries
Handle hijackOnly holder of signing key can rotate
Silent key swapCLI warns if trust anchor fingerprint changes

What the Registry Never Sees

  • Plaintext messages
  • Encryption private keys
  • Message metadata beyond handle → pubkey mapping

The registry cannot read, decrypt, or enumerate any inbox contents.


Operational Advice

  • Back up registry.store.json frequently.
  • Never rotate the root key unless all clients are prepared to re‑trust.
  • Host registry behind Tor gateway if anonymity is required.