did-btcr2-js

ADR 029: TLS-Only Confidentiality; Signed Envelopes for Authenticity

Status: Accepted

Date: 2026-04-22

Branch / PR: aggregation/http-transport Depends on: ADR 028

Context

The Nostr transport uses NIP-44 v2 for end-to-end confidentiality of directed messages, giving the service operator no visibility into participant-service payloads. The HTTP transport had to answer: does it preserve this property, and at what cost?

Two layers need consideration:

HTTPS (TLS 1.3) solves the first. The second requires message-layer encryption, which on Nostr is NIP-44 over ECDH.

Separately, authenticity / non-repudiation needs to be preserved so a third party can prove “did X sent message M at time T” without relying on the operator’s word.

Options considered

  1. Port NIP-44 v2 to HTTP bodies. Ciphertext in POST bodies; unchanged threat model. ~10 lines of code, reuses existing nostr-tools dependency.
  2. Use HPKE (RFC 9180). A purpose-built modern hybrid PKE scheme. More auditable than NIP-44; adds a dependency.
  3. TLS-only, message-layer BIP340 signatures for authenticity. Operator sees plaintext of directed messages; signatures prevent impersonation and provide non-repudiation at the protocol layer.
  4. TLS-only, no authenticity layer. Rely entirely on TLS + session tokens.

Decision

Option 3. Every HTTP request body and SSE event carries a SignedEnvelope:

{ v, from, to?, timestamp, nonce, message, sig }

where sig = BIP340(x-only-sk(from), sha256(canonicalize({v, from, to, timestamp, nonce, message}))).

Server verification checks the signature against the sender’s pubkey, rejects stale timestamps (±60s skew), and rejects replayed (from, nonce) pairs. TLS provides confidentiality in transit; operator plaintext access is an accepted consequence.

Consequences

Positive

Negative

Explicitly accepted trade-offs

References