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:
-
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.
- A handle (e.g.
-
Certificate issuance
- The registry signs a canonical certificate object:
{ "handle": "alice", "encPub": "<base64-x25519-public-key>", "keyId": "v1", "expiresAt": 1735689600 } -
Trust anchor distribution
- The root signing public key is distributed through
/keys/ - Clients verify all certificates using this root key.
- The root signing public key is distributed through
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /keys/ | Returns the current root signing public key |
| GET | /keys/:handle | Returns signed certificate for a handle |
| POST | /register | Register or rotate a handle certificate |
| POST | /challenge | Request registration challenge |
| POST | /verify | Verify 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
- Client requests a challenge
- Registry returns a random nonce
- Client signs nonce using their signing key
- Registry verifies and stores the new certificate
- 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
| Threat | Mitigation |
|---|---|
| MITM during registration | Challenge‑response signing |
| Registry database tampering | Root‑signed certificates invalidate forged entries |
| Handle hijack | Only holder of signing key can rotate |
| Silent key swap | CLI 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.jsonfrequently. - Never rotate the root key unless all clients are prepared to re‑trust.
- Host registry behind Tor gateway if anonymity is required.