Sealed envelopes
Where TLS ends at an edge, a sealed envelope carries the call through: encrypted to the recipient’s leaf key, signed by the sender’s, with the sender hidden inside.
Why an envelope
Plain mTLS ends where TLS ends. A terminating tunnel edge reads whatever crosses it and sees no client certificate, so behind such a pipe both confidentiality and caller identity need a carrier that survives termination. The sealed envelope is that carrier: HPKE encryption to the recipient’s leaf key plus a detached signature by the sender’s leaf key. One key does all three jobs — TLS, signature, sealing — and it belongs to a leaf under a root (§ 13). Sealing is negotiated by the card’s X-PACT-SEAL: none, optional or required (§ 13.4).
Four members, one key named
protected is the canonical-JSON header, the HPKE associated data: v (2), suite, kid — the fingerprint of the recipient leaf key this is sealed to — msg_id, ts, exp and cty. There is no from and no to: the sender is the chain inside the ciphertext, the recipient is the key. enc is the HPKE encapsulated key, of exactly the suite’s length; ct the ciphertext; sig the sender’s signature over the three decoded members concatenated. Each member is base64url without padding in its one canonical spelling, and a receiver refuses any other (§ 13.1). The suite follows the recipient’s key and nothing else, so no choice is left on the wire for a sender to make badly.
The chain travels once
The plaintext of a request is one bare JSON object of method, params, and exactly one of chain and leaf. A sender carries its chain — leaf and root — on first contact and in its first envelope to each contact after a renewal; after that it names its leaf by fingerprint, about fifty bytes. A receiver that cannot verify the signature under a leaf it holds answers chain_required, in plaintext and with no data, and the sender resends with the chain. The answer is the same in every case, so it tells a stranger nothing about who the receiver knows, and a blocked contact meets it exactly as a stranger does (§ 13.2). The result of a sealed request is sealed back to the caller, errors included once the request envelope has been opened.
Opening, in order
Receivers validate in a fixed order and reject at the first failure: decode protected; check v and suite; resolve kid to a leaf key this endpoint holds for the identity served at that path, answering certificate_renewed with the current chain when it names a key this endpoint once held; check the suite is the one the key takes; open; require the plaintext’s three members; verify the signature under the named leaf or the validated chain; enforce time — now < exp, and ts within 300 seconds of now, since every envelope is delivered directly; enforce msg_id idempotency, a replayed envelope being acknowledged with its original result and never re-executed; then dispatch (§ 13.3).
What sealing does not give
No forward secrecy: HPKE in Base mode to a long-lived key means a later compromise of a leaf key decrypts ciphertext recorded while it was current; the 300-second window and the leaf’s lifetime bound the exposure, not fix it. Post-quantum sealing is deferred by decision, with the path settled: a hybrid KEM key carried in the leaf as an extension, and one suite in place of two. Metadata is not nothing: a carrier sees kid, timing and sizes, and can tie every message to one recipient key for that leaf’s life; it no longer sees who sent it (§ 13.5).