SEMP logo: a sealed envelope with a wax seal

SEMP

Sealed Envelope Messaging Protocol.

A federated messaging protocol with message-layer encryption, a typed-visibility envelope, DNS-based peer discovery, and an in-protocol identity and key-distribution model. Intended as an SMTP successor for deployments that require end-to-end encryption and metadata minimization at the protocol layer.

Two independent implementations interoperate end-to-end under both baseline (X25519) and post-quantum (Kyber768+X25519) suites, with cross-language test vectors gating every release.

semp-go semp-ts Cross-impl interop verified

Protocol properties

SEMP defines a single wire format and session model covering submission, federation, retrieval, and key distribution. The properties below describe what the protocol itself guarantees, independent of any specific deployment.

Message-layer encryption

Enclosure content is encrypted under per-recipient keys derived at composition time. Servers route and store envelopes without decrypting the enclosure.

Typed envelope visibility

Each envelope is a four-layer structure (postmark, seal, brief, enclosure) with explicit visibility per layer. The boundary between server-readable and end-to-end fields is enforced by the construction.

DNS-based federation

Peer servers locate each other through SRV and TXT records under _semp._tcp.<domain>. Federation handshake reuses the same Noise-style state machine as client sessions.

In-protocol identity

Each domain publishes signing and encryption keys. User keys are signed by the domain authority. Identity binding is part of the envelope construction itself.

Hybrid post-quantum option

The pq-kyber768-x25519 suite provides hybrid post-quantum key agreement using the same envelope shape and session-key schedule as the classical baseline. Suite negotiation is part of the handshake.

Multiple transports

WebSocket (RFC 6455), HTTP/2 (RFC 9113), and QUIC (RFC 9000) bindings are normative. Transport selection is independent of session and envelope semantics.

Try it in your browser

The SEMP Explorer at explorer.semp.dev drives the semp-ts library through every step of an envelope exchange, federation handshake, client handshake, and discovery round-trip. Each operation appears as a trace step with its actual input and output bytes, a link back to the spec section that defines it, and a paste-into-Node snippet that reproduces the step locally with no SEMP-specific build.

Wire-level visibility

Every cryptographic operation shows its bytes: HKDF outputs, AEAD ciphertexts, KEM ciphertext + shared secret, Ed25519 signatures, MAC tags. The session log isn't a recording; the library runs in the tab and produces the bytes you see.

Both suites, side by side

Flip the suite toggle in the header to rerun the same scenario under the post-quantum hybrid pq-kyber768-x25519. The trace surfaces the byte-length deltas (Kyber768 keys 1184B, ciphertexts 1088B) without changing the envelope shape.

Two-tab interaction

Type another visitor's address into the recipient field to send to a real peer over HTTPS, or leave it empty to wait as the recipient yourself. The trace then renders what arrived, what the server verified, and the bytes the recipient's user-side decrypted.

Reproduce locally

Every step carries a self-contained Node script that reproduces the operation against the same library version, behind a copy button. No project scaffold, no SEMP-specific build: npm i the listed primitives and the script runs.

Must-reject scenarios

Eleven recorded rejection cases run the spec-mandated verification chain on a tampered envelope, attachment, delivery receipt, or first-contact token, and surface where the chain fails and why.

Slow observation

Toggle slow-observation mode and the trace inserts a real pause between operations: a federation handshake takes ten seconds instead of one, every step held long enough to read before the next arrives. Not a UI animation, an actual wait at the wire.

Non-goals

Boundaries the protocol explicitly does not attempt to enforce. Reviewers and implementers should expect these to remain out of scope for v1.0.0.

Eliminating spam universally

SEMP raises the cost of abuse through domain-based reputation, proof-of-work, first-contact challenges, and scoped delegation. Determined abuse at scale is a social and economic problem that no protocol can solve alone.

Replacing SMTP overnight

SEMP is designed for incremental adoption. Users may run SEMP and legacy mail accounts in parallel during a transition period; clients present both in a unified inbox with persistent origin indicators. The SEMP server itself stays SEMP-only; legacy interop happens at the client.

Guaranteeing anonymity

Metadata protection is significantly stronger than SMTP. The anonymity guarantees of mix networks or Tor are out of scope for the base protocol. Operators who require stronger anonymity may layer additional infrastructure underneath without protocol-level objection.

Eliminating the key-fetch intent leak

No federated messaging protocol can hide the fact that server A contacted server B. SEMP supports multiple key-fetch mechanisms (speculative batch crawling, third-party key relay, direct well-known fetch) with documented privacy and infrastructure tradeoffs; operators choose the order and fallback.

Mandating one cryptographic algorithm forever

SEMP specifies minimum acceptable algorithms and supports negotiation of stronger suites at handshake time. The two named suites in v1.0.0 are x25519-chacha20-poly1305 and pq-kyber768-x25519; future suites enter through the same negotiation surface without breaking the wire format.

Differences from SMTP

A neutral comparison of architectural and wire-level differences. SEMP and SMTP both target federated person-to-person messaging; the lines below describe where their protocol designs diverge.

Property
SMTP
SEMP
Trust anchor
Trust derives from IP-address reputation, accumulated and adjudicated by a small number of large operators using opaque criteria. New operators face a structural disadvantage entering the network.
Trust derives from cryptographic domain identity. Reputation is built from signed observation records (REPUTATION.md), persists across IP changes, can be transferred across operator changes, and is independently verifiable by any receiving server.
Identity binding
Bolt-on via SPF (RFC 7208), DKIM (RFC 6376), DMARC (RFC 7489), and ARC (RFC 8617). Sender authentication and message integrity are separate layers over DNS.
In-protocol. Domain signing keys are distributed via the SEMP_KEYS request; user keys are signed by the domain authority. Binding is integral to envelope construction.
Encryption boundary
Transport-level via opportunistic STARTTLS (RFC 3207). Message-layer encryption is out-of-band (PGP / S/MIME) and rarely deployed by default.
Message-layer encryption is mandatory. Per-recipient AEAD wrap of the enclosure; transport TLS is also required, as a secondary outer layer.
Message integrity
DKIM (RFC 6376) provides a selective-header signature bound to the sending domain's outbound MTA. Body modifications by relays, mailing-list expansion, and forwarding routinely invalidate DKIM signatures.
Two independent integrity proofs cover the same canonical envelope bytes: seal.signature (domain key, verifiable by any routing server) and seal.session_mac (verifiable by the receiving server). An optional inner signature over the enclosure plaintext binds authorship to the sender's identity key and survives forwarding.
Header confidentiality
From, To, Cc, Subject, and Message-ID are visible to every relay along the path.
Subject and message body live inside the encrypted enclosure. Sender and recipient addresses live in the brief, decryptable only by the recipient server (for policy enforcement) and the recipient client.
Forward secrecy
Limited to TLS session lifetime when STARTTLS is in use; archived spool files at every hop are typically plaintext.
Per-session keys derived from an ephemeral handshake, rekeyed at 80% of session TTL. Stored envelopes remain encrypted at rest.
Replay protection
Best-effort de-duplication on Message-ID; no protocol-mandated mechanism.
Postmark expiry plus a session MAC over canonical envelope bytes (K_env_mac).
Peer discovery
MX records (priority and fallback list).
SRV records under _semp._tcp.<domain> plus a TXT record advertising the protocol version.
Deployment surface
Requires unblocked outbound TCP port 25 (commonly blocked on residential and lower-tier hosting), warm IP reputation, configured reverse DNS, and aligned SPF / DKIM / DMARC records.
Runs over WebSocket, HTTP/2, or QUIC on operator-chosen ports (typically 443). Same infrastructure as any TLS-served web application; no IP warming, no reverse-DNS prerequisites.
Submission and retrieval
Distinct protocols: SMTP submission (RFC 6409, port 587), retrieval via IMAP (RFC 9051) or POP3 (RFC 1939).
Single protocol covering submission, fetch, key requests, federation, and rekeying within one session model.
Delivery feedback
Acceptance acknowledged via per-hop 250 OK; failure via DSN (RFC 3464), which is commonly disabled, asynchronous, and forgeable. Servers may accept-then-silently-discard, leaving senders with false confirmation while recipients remain unaware that a message existed.
Every delivery attempt resolves to one of two wire acknowledgments from the recipient server (delivered or rejected) with a machine-readable reason code, signed by the recipient domain. A recipient operating in silent mode for privacy or anti-harassment reasons withholds any wire response; the sender's home server then classifies the timeout as silent for sender-side bookkeeping. Silent acceptance with intent to discard is prohibited.
Address verification
VRFY and EXPN (RFC 5321) usually disabled to prevent enumeration; no in-protocol address-validity probe remains.
SEMP_KEYS request returns signed key records or not_found per explicit address. Per-address existence is unobservable; non-existent and policy-rejected addresses receive identical responses in shape, size, and timing (DESIGN.md §2.7).
Crypto agility
STARTTLS negotiates TLS cipher suites at the transport layer; message-layer crypto (PGP / S/MIME) negotiated separately.
One named suite per session, negotiated in the handshake. Classical (x25519-chacha20-poly1305) and hybrid post-quantum (pq-kyber768-x25519) share envelope and session-key shape.

Frequently asked

The complete design rationale lives in the spec's extensions.md and the topic-specific drafts. The questions below summarize the most common reviewer entry points.

Why a new protocol instead of extending SMTP?
SMTP's metadata exposure is structural. The relay model requires plaintext envelope metadata (sender, recipient, subject, routing path) for messages to be delivered. No extension can encrypt this without replacing the relay model, and replacing the relay model is replacing the protocol. Body-only encryption (PGP, S/MIME) has been available for decades and leaves the metadata problem, the IP-reputation problem, the silent-discard problem, and the extensibility problem untouched. SEMP addresses these as a unified design because they are architecturally interconnected.
Isn't SEMP just a web service, given it runs over WebSocket / HTTP/2 / QUIC?
SEMP is a federated protocol that uses web transports. Web transports are a deployment choice: they pass through firewalls, NATs, and proxies; they get TLS through existing certificate infrastructure; they avoid port-25-style blocking on residential connectivity. SEMP could run over raw TCP with custom framing and every protocol property would be identical. The transport is a pluggable layer defined in handshake.md. SMTP runs over TCP without anyone calling it "merely a TCP service."
How is mailing-list delivery handled without a list-server intermediary?
Two mechanisms. Group addressing: list membership is resolved on the sender's client, which generates per-recipient envelopes encrypted to each subscriber individually. Delegated clients: a user registers a mailing-list service as a delegated client with a scoped device certificate that restricts which addresses it can reach (discovery.md §10.3). No intermediary reads or rewrites messages, so the DKIM-breakage and ARC-workaround problems familiar from SMTP do not arise. For very large groups, an MLS-based extension is sketched in envelope.md §4.4 for logarithmic-cost group key management.
How does forwarding preserve sender identity across hops?
Forwarding is performed on the recipient's client. The client composes a new envelope to the forwarding target; the original encrypted enclosure, including the original sender's identity-key signature, is preserved verbatim inside enclosure.forwarded_from of the new envelope. The new recipient verifies the original sender's signature against the original sender's published identity key, giving cryptographic provenance regardless of how many times the message has been forwarded. Automatic forwarding is handled through delegation with a send scope restricted to the forwarding target.
What about delivery status notifications and read receipts?
Delivery status is core. Every delivery attempt resolves to one of two wire acknowledgments from the recipient server (delivered or rejected) with a machine-readable reason code, signed by the recipient domain. A recipient operating in silent mode for privacy or anti-harassment reasons withholds any wire response; the sender's home server classifies the resulting timeout as silent for sender-side bookkeeping. Sender-side queue state (attempt counts, next attempt time, terminal state) is exposed to the submitting client per delivery.md §2. Read receipts (MDN equivalents) are not defined: they compel the recipient device to reveal viewing behavior to a sender with no independent claim on that information, and most privacy-respecting clients strip them today. Vendors who require them MAY define a vendor extension under their own namespace per extensions.md.
How are autoresponders / out-of-office replies handled?
SEMP replaces the autoresponder message with a recipient-status field on the existing delivered acknowledgment (delivery.md §1.6). When the acknowledgment is delivered, the recipient server attaches state (available / away / do_not_disturb), an optional freetext message, and an optional until timestamp. The sender learns "recipient is away until July 1" from the acknowledgment the server already generated, with no separate message and no loop risk. Status visibility is opt-in per user, per domain, or per peer. Richer automated responses are a client-layer feature, run as a delegated client with restricted send scope.
Where is server-side search and rules?
Server-side full-text search is incompatible with end-to-end encryption: the server cannot search content it cannot read. Every encrypted messaging system inherits this constraint. The server can still index brief metadata (sender address, domain, timestamps, thread and group identifiers) because it can decrypt the brief; metadata search covers "messages from this sender" and "messages in this thread" without exposing content. Organizations that need server-side content search run a delegated client with receive permission that decrypts and indexes within their own infrastructure; the delegation is explicit, scoped, and revocable. Sieve-style rules apply at the same boundary: brief-level rules run on the server, content-level rules run in the client (or in a scoped delegated client). The user controls who indexes their mail, which is a property SMTP never offered.
What about VRFY, EXPN, and address enumeration?
The SEMP_KEYS request returns signed key records or not_found per explicit address. Per-address existence is unobservable: non-existent and policy-rejected addresses receive responses identical in shape, size, and timing. There is no protocol verb equivalent to VRFY or EXPN, and mailing-list expansion happens on the sender side, so the server never sees list membership.
How does SEMP handle internationalized addresses?
SEMP is UTF-8 native. All JSON fields, including address fields in the brief, are UTF-8 encoded. Internationalized addresses require no special handling or extensions. This is a structural advantage over SMTP, which required the SMTPUTF8 extension (RFC 6531) to support non-ASCII addresses.
Is the handshake too slow for messaging at scale?
The handshake is two round trips in the normal case (four messages); three round trips when proof-of-work is required. On modern web transports over persistent connections this is tens to hundreds of milliseconds. Sessions amortize the cost: once established, envelopes flow without re-handshaking until the session expires. For active federation pairs the per-envelope handshake cost approaches zero. For comparison, SMTP with STARTTLS, SPF, DKIM, DMARC, and reputation checks involves more round trips and external DNS lookups than SEMP's handshake.
Is SEMP post-quantum secure?
The preferred suite is pq-kyber768-x25519, a hybrid combining ML-KEM-768 (FIPS 203, lattice-based key encapsulation) with X25519 (classical elliptic-curve Diffie-Hellman). If either component is broken the other still protects the session secret. This addresses the harvest-now-decrypt-later threat. Post-quantum protection applies to both the handshake (session key exchange) and the envelope (symmetric key wrapping). Implementations MUST prefer the hybrid suite when both parties support it and MUST NOT downgrade when a stronger suite is available.
What happens if a server is compromised?
A compromised recipient server can read brief metadata (sender addresses, timestamps, threading) for current and future envelopes. It cannot read enclosure content (subject, body, attachments). It cannot decrypt past envelopes: session keys are ephemeral and erased after each session. A compromised sender server can forge new envelopes (it holds the domain key) but cannot decrypt past envelopes it relayed. Domain-key compromise is handled via revocation and rekeying (discovery.md §8); user-key compromise is bounded by the per-recipient AEAD wrap.
SEMP vs. DIME?
DIME (2013-2017) shared SEMP's intent: layered encryption, metadata protection, a new transport (DMTP). DIME's Next-Hop / Envelope / Content layers map closely to SEMP's postmark / brief / enclosure. SEMP differs in three ways. DIME maintained SMTP backward compatibility at the server layer with Trustful / Cautious / Paranoid modes that muddied the security story; SEMP is SEMP-only at the server and pushes legacy interop to the client. DIME had no reputation or anti-abuse system; SEMP's trust gossip, proof-of-work, and domain-based reputation are central. DIME did not reach a usable implementation or sustain a community. SEMP ships protocol libraries and a vector corpus from day one.
SEMP vs. PGP / S/MIME?
PGP and S/MIME encrypt message bodies but leave all metadata in plaintext. They bolt encryption onto SMTP without changing the transport. Key management is manual and notoriously painful. SEMP protects metadata structurally by designing the envelope format and transport together, and automates key management through server-mediated key discovery with a transparency log.
SEMP vs. MLS (RFC 9420)?
MLS is a group key-agreement protocol. It addresses efficient asynchronous group key establishment but defines no message format, no routing, no delivery semantics, no reputation, and no blocking. SEMP and MLS operate at different layers and are complementary: SEMP could adopt MLS for large-group key management as a future extension. The core SEMP envelope uses per-recipient key wrapping because that model is stateless, which matches email's storage-for-years and recover-from-backup usage.
SEMP vs. Signal Protocol?
Signal provides end-to-end encryption with forward secrecy and post-compromise security for two-party and small-group messaging. It is centralized (all traffic flows through Signal's servers), tied to phone numbers, and does not support federation. SEMP provides similar cryptographic properties in a federated architecture with email-style addressing and domain-based trust.
SEMP vs. ProtonMail / Tuta?
ProtonMail and Tuta are vertically integrated products with their own server and client implementations. They encrypt at rest on their servers and offer end-to-end encryption between their own users; communication with external providers is either unencrypted SMTP or a workaround (click a link to read the encrypted message). They have proven market demand for encrypted email but have not solved the federation problem. SEMP is the protocol layer that would let independent providers interoperate securely.

Envelope structure

An envelope is a four-layer structure. Each layer has a defined visibility class. Layer boundaries are enforced cryptographically through signatures and AEAD wraps; an honest server cannot read the enclosure, and a misbehaving server cannot forge a brief without detection.

Postmark
From-domain, to-domain, session ID, expiry. Required for routing.
Public
Seal
Domain signature, session MAC, per-recipient key wraps.
Verifiable
Brief
From-address, to-addresses, message ID, timestamps.
Server-readable
Enclosure
Subject, body, attachments, structured payload.
End-to-end only

Federation

A typical cross-domain delivery sequence. Peer discovery is via DNS SRV. The federation handshake reuses the client handshake state machine; domain keys are fetched on demand via SEMP_KEYS over an established federation session.

[email protected]                Server A              Server B              [email protected]
     |                            |                     |                     |
     |-- register (public keys) ->|                     |                     |
     |<- domain keys -------------|                     |                     |
     |                            |                     |                     |
     |-- handshake -------------->|                     |                     |
     |<- session established -----|                     |                     |
     |                            |                     |                     |
     |-- encrypted envelope ----->|                     |                     |
     |                            |-- DNS SRV --------->|                     |
     |                            |<- srv target -------|                     |
     |                            |                     |                     |
     |                            |-- fetch domain key->|                     |
     |                            |<- domain key -------|                     |
     |                            |                     |                     |
     |                            |-- federation ------>|                     |
     |                            |   handshake         |                     |
     |                            |<- session ----------|                     |
     |                            |                     |                     |
     |                            |-- forward envelope->|                     |
     |                            |<- delivered --------|                     |
     |<- delivered ---------------|                     |                     |
     |                            |                     |-- fetch ----------->|
     |                            |                     |<- encrypted env ----|
     |                            |                     |                     |
     |                            |                     |   (decrypt locally) |

Cross-implementation conformance

Two protocol libraries (Go, TypeScript), two reference server implementations, and two reference client implementations are maintained at parity. Each release is gated on the cross-language test vector corpus; the federation harness exercises every server-client combination end-to-end.

Go server
TS server
Go client
Verified
Verified
TS client
Verified
Verified

Each matrix cell exercises the full session lifecycle: registration, handshake, submission, federation, fetch, decryption, signature verification. Envelopes signed by one implementation decode and verify under the other. The wire format is fixed at v1.0.0 and pinned by the test vector corpus at semp-spec/vectors/v1.0.0.

Building from source

Each reference repository ships a Go and a TypeScript implementation under impl/go and impl/ts. The two implementations are interchangeable on either side of a session.

Go server
git clone https://github.com/semp-dev/semp-reference-server.git
cd semp-reference-server/impl/go
go build -o semp-server ./cmd/semp-server
cp ../../shared/config/config.example.toml semp.toml
./semp-server -config semp.toml
TS server
git clone https://github.com/semp-dev/semp-reference-server.git
cd semp-reference-server/impl/ts
npm install && npm run build
node dist/main.js \
  --config ../../shared/config/config.example.toml
Go client
git clone https://github.com/semp-dev/semp-reference-client.git
cd semp-reference-client/impl/go
go build -o semp-client ./cmd/semp-client

./semp-client -config alice.toml register -password CHANGEME
./semp-client -config alice.toml send \
  -to [email protected] -subject "Hello" -body "First SEMP message"
./semp-client -config bob.toml fetch
TS client
git clone https://github.com/semp-dev/semp-reference-client.git
cd semp-reference-client/impl/ts
npm install && npm run build

node dist/cli.js -c alice.toml register -password CHANGEME
node dist/cli.js -c alice.toml send \
  -to [email protected] -subject "Hello" -body "First SEMP message"
node dist/cli.js -c bob.toml fetch
DNS records
semp.example.com.          3600  IN  A     203.0.113.10
_semp._tcp.example.com.    3600  IN  SRV   10 1 443 semp.example.com.
_semp._tcp.example.com.    3600  IN  TXT   "v=semp1"

Example session output

Captured logs from a federation between two independent SEMP servers. Servers located each other through DNS SRV records and exchanged domain signing keys via the federation handshake; no static peer configuration was provided.

Cross-domain: [email protected] sends to [email protected]

$ ./semp-client -config alice.toml send -to [email protected] \
    -subject "Cross-domain" -body 'First federated SEMP message!'
level=INFO msg=connected server=wss://semp.alpha.com/v1/ws
level=INFO msg="session established" session_id=06ERB6WQZMTY7HBDE1GYWATTS4 ttl=5m0s
level=INFO msg="envelope sent" [email protected] to=[[email protected]]
Envelope submitted: [email protected]
  [email protected]: delivered

[email protected] fetches

$ ./semp-client -config bob.toml fetch
level=INFO msg=connected server=wss://msg.beta.com/v1/ws
level=INFO msg="session established" session_id=06ERB71K2FSFG12EVJ2XCSXK08 ttl=5m0s
level=INFO msg="fetched envelopes" count=1 drained=true

--- Message [email protected] ---
From:    [email protected]
To:      [email protected]
Subject: Cross-domain
Body:
First federated SEMP message!

1 message(s) fetched.

Cryptographic suites

Two suites are normative in v1.0.0. Both share the same envelope structure, signature framework, and five-key session schedule. The suite is selected at handshake time and recorded in the postmark.

Baseline

x25519-chacha20-poly1305

  • X25519 key agreement
  • ChaCha20-Poly1305 AEAD
  • HMAC-SHA-256 message authentication
  • HKDF-SHA-512 key derivation
  • Ed25519 signatures
Post-quantum

pq-kyber768-x25519

  • Hybrid Kyber768 + X25519 KEM
  • Same symmetric primitives as baseline
  • Same five-key session derivation
  • Forward secrecy under quantum adversaries
  • Wire-format-compatible upgrade path
Session

Five-key derivation

  • K_enc_c2s · K_enc_s2c
  • K_mac_c2s · K_mac_s2c
  • K_env_mac for envelope MAC
  • In-session rekeying at 80% TTL

Repositories

Specification under Creative Commons Attribution 4.0. Implementations under MIT.

Status and work in progress

SEMP is in a phased rollout: anchor the wire format, submit at IETF, gather external review, expand language coverage. The current phase is documented below for prospective implementers and reviewers.

Wire format v1.0.0 fixed

Cross-language test vector corpus locked. Two protocol libraries pass the corpus byte-for-byte. Polyglot reference server and client repositories pass the cross-implementation federation matrix.

Complete

IETF Internet-Draft

SEMP is structured as an eight-draft series for submission to the IETF.

In progress

External cryptographic review

Outreach to the IRTF CFRG mailing list and to academic cryptography groups. Substantive feedback is absorbed into the specification before further implementations propagate from the v1.0.0 wire format.

In progress

Additional language implementations

Library ports beyond Go and TypeScript, in declared priority order: Rust, Python, Swift, Kotlin. Each port is required to pass the cross-language test vector corpus and join the federation matrix before being declared conformant.

Planned

Test vector corpus expansion

Coverage extension into error paths, federation edge cases, and fuzzing-derived corner cases. New vectors that surface specification ambiguity feed the next draft revision.

Ongoing