Skip to content

Security Model

Directory routes value the same way DNS routes connections and SMTP routes messages. The security model is the same too. The threats are the same. The privacy expectations should be the same.

Trust anchor

DNS is the root of trust. A domain’s operator controls two DNS records:

  • _drs._tcp SRV — where the node lives
  • _drskey TXT — the public key that signs routing contracts

If you control these records, you control the routing. If an attacker controls these records, they control the routing. There is no secondary trust layer. This is the same model as MX records for email and A records for web traffic. It is well-understood, battle-tested, and imperfect.

DNSSEC

DNS without DNSSEC is unauthenticated. A cache poisoning attack can substitute a fake public key, stand up a fake node, and sign valid-looking contracts that route to the attacker’s destination. The Ed25519 signature on the routing contract protects against tampering after discovery. DNSSEC protects discovery itself.

DNSSEC is strongly recommended for any domain running a Directory node. See the DNS Records page for setup instructions.

TLS

HTTPS provides transport security between the client and the node. TLS prevents a network observer from reading or modifying resolve requests and routing contracts in transit.

TLS does not authenticate the node’s identity beyond the certificate. CDNs terminate TLS. Certificates can be misissued. The Ed25519 signature on routing contracts is the protocol’s own authentication — it proves the contract was issued by whoever controls the domain’s private key, regardless of what happens at the transport layer.

Routing contract integrity

Every routing contract is signed with Ed25519. The signature covers the canonical JSON serialization of the contract (sorted keys, no whitespace, signature field excluded). The public key for verification is in DNS.

This means:

  • A contract cannot be modified in transit without invalidating the signature
  • A contract cannot be forged without the domain’s private key
  • A contract can be verified by any third party without contacting the issuing node
  • An expired contract is rejected even if the signature is valid

The signing model is DKIM for routing. The same way DKIM lets any mail server verify that a message really came from the sending domain, Directory lets any client verify that a routing contract really came from the node’s domain.

What the protocol does not authenticate

The capability manifest at /.well-known/directory.json is not signed. It is served over HTTPS and cached. A CDN compromise or cache poisoning could serve a modified manifest.

The manifest is informational — it tells clients what the node accepts, not where to send money. The routing contract handles delivery, and the contract is signed. A tampered manifest could cause a client to believe a node doesn’t support an asset type (denial of service) or to attempt a resolution that fails. It cannot redirect funds.

Client requirement: Clients MUST verify that the domain they queried matches their own resolution target. Do not trust the domain field in the manifest to determine where to resolve.

Privacy

Routing is metadata. When Bob resolves alice@gmail.com, the following parties learn the following things:

WhoWhat they learn
Gmail (the operator)Someone from Bob’s IP intends to pay Alice. Approximate time.
DNS resolverBob’s machine queried _drs._tcp.gmail.com — a Directory lookup is happening.
Network observerWithout DoH/DoT, the DNS query is visible. The HTTPS connection to Gmail’s node is visible (but contents are encrypted).
The blockchainAfter settlement, the destination address and amount are public (for on-chain transfers).

This is not unique to Directory. This is how routing works. When Bob sends Alice an email, Gmail sees the envelope. When Bob visits a website, the DNS resolver sees the query. When Bob sends an on-chain transfer, the ledger sees the destination.

The instinct is to treat money routing as more sensitive than message routing. It isn’t. It is the same act — resolving a human identifier to a delivery instruction — and it deserves the same privacy expectations. Reading someone’s messages was once unthinkable. Surveilling someone’s financial routing is currently normalized. Neither should be.

Operator responsibility

Operators see resolution requests. This is inherent to operating the node, the same way running a mail server means seeing envelope metadata. Operators SHOULD:

  • Not log resolution requests beyond what is needed for abuse prevention
  • Not correlate resolution metadata with on-chain activity
  • Not sell or share resolution data
  • Rotate destination addresses when possible to limit on-chain correlation

Destination privacy

If an operator returns the same wallet address for every resolve, all payments to that address are linkable on-chain. Operators who care about recipient privacy should generate unique deposit addresses per resolution. The protocol supports this — the destination field is opaque and can be anything the operator controls.

Key management

The Ed25519 private key is the most sensitive secret in a Directory node. Whoever holds it can sign routing contracts for any address on the domain.

Storage

The private key should be stored in the platform’s secret management:

  • Cloudflare Workers: Worker Secrets (encrypted at rest, not visible in dashboard)
  • AWS: Secrets Manager or Parameter Store
  • Self-hosted: Environment variable, not committed to source control

Rotation

There is no key rotation protocol in v1. When rotating keys:

  1. Generate a new keypair
  2. Update the DNS TXT record with the new public key
  3. Update the node’s signing key secret
  4. Wait for DNS propagation (check TTL)

During propagation, some clients may cache the old key and reject contracts signed with the new key. The spec requires clients to re-fetch the DNS key once on verification failure, which handles most rotation scenarios.

A future version may support multiple concurrent _drskey records with key IDs (kid) to enable graceful rotation.

Compromise

If the private key is compromised:

  1. Generate a new keypair immediately
  2. Update the DNS TXT record
  3. Update the node’s signing key
  4. Set the DNS TTL low before rotation to minimize the window

During the propagation window, the attacker can still sign valid contracts. There is no revocation mechanism beyond DNS propagation. This is the same constraint as DKIM key compromise — the mitigation is the same too.

Abuse model

Directory does not introduce a new trust layer. It inherits DNS’s trust model, including its abuse handling mechanisms:

  • Domain disputes are handled by ICANN and registrars (UDRP)
  • Phishing domains are handled by registrar abuse teams and browser safe-browsing lists
  • Spoofing requires control of the target’s DNS records — the same bar as spoofing a website

An attacker cannot spoof gmail.com routing without compromising Google’s DNS. They can register gmai1.com and run a node — but that’s a domain impersonation problem, handled by the same mechanisms that handle phishing websites today.

The protocol does not attempt to solve problems that DNS already solves. It does not attempt to solve problems that DNS cannot solve.

Address enumeration

The /resolve endpoint returns different HTTP status codes for existing addresses (200) and missing addresses (404). An attacker can probe for valid addresses.

Operators concerned about enumeration SHOULD implement rate limiting on the /resolve endpoint. The protocol does not specify a rate limiting mechanism — this is an operator decision, the same way SMTP rate limiting is a mail server decision.

Request validation

Implementations SHOULD:

  • Reject request bodies over 4KB (a resolve request is typically under 200 bytes)
  • Validate Content-Type: application/json
  • Reject malformed JSON before any processing
  • Reserve internal key names (e.g., _root) from user address registration