Skip to content

Build encrypted group messaging on Nostr (Marmot/MLS)

You want a group chat where only the members can read the messages — no central server, no phone numbers, and ideally not even a record of who is talking to whom. That is exactly what Marmot is for: it runs the IETF MLS group- encryption standard over Nostr’s decentralized network. This guide explains what the pieces are, how they fit, and — just as importantly — where the rough edges are.

Marmot = MLS (the cryptography) + Nostr (the identity and transport).

  • MLS (RFC 9420) is the IETF’s Messaging Layer Security standard for end-to-end-encrypted group messaging. It gives you forward secrecy (compromising today’s keys doesn’t expose past messages) and post-compromise security (the group heals after a member rotates keys).
  • Nostr provides the identity (your own keypair — no phone or email) and the transport (relays you choose, not a central server).

Marmot is the specification that ties them together — a set of “MIPs” (Marmot’s spec documents) defining which Nostr event kinds carry MLS KeyPackages, group invites, and encrypted messages. White Noise is the production reference client built on it.

Why MLS over Nostr (and not something else)

Section titled “Why MLS over Nostr (and not something else)”

Marmot’s own framing: Signal has excellent E2EE but centralized infrastructure; plain Nostr DMs (NIP-04/NIP-17) lack forward secrecy and real group messaging. Marmot aims to combine MLS’s proven group cryptography with Nostr’s censorship-resistance and identity freedom — encrypting both message content and, as a goal, the metadata of who is in a group.

You do not implement any of the cryptography yourself. You assemble vetted, license-verified libraries and wire up the Nostr event choreography. The crypto lives in audited code; your job is integration.

LayerWhat it doesUse
MLS coreThe actual group cryptography (RFC 9420)openmls (Rust) · ts-mls (TS)
Marmot engineMarmot’s high-level API over MLS — KeyPackages, groups, Welcomes, message encryptionmdk-core (Rust, the engine inside White Noise) · @internet-privacy/marmot-ts (TS)
MediaEncrypted images/files, stored off-relayBlossom protocol · a Blossom server · blossom-client-sdk
Reference clientThe production app that proves it worksWhite Noise

The moving parts, in plain terms (event kinds pinned from the MIPs at commit 21a67b2):

  1. Identity → KeyPackage. Your Nostr keypair becomes your MLS identity. You publish a KeyPackage (kind:30443) so others can invite you, and advertise where your KeyPackages live with a KeyPackage relay list (kind:10051).
  2. Group + Welcome. A group is an MLS group tagged with the Marmot Group Data Extension (0xF2EE). To add someone, you fetch their KeyPackage and send a Welcome (kind:444) gift-wrapped for privacy (NIP-59).
  3. Messages. Group messages (kind:445) are encrypted with a key the MLS library derives per epoch (ChaCha20-Poly1305). New members read them from the relays named in their Welcome.
  4. Media (optional). Files are encrypted, stored on Blossom by their hash, and shared with a small imeta tag in the message.

The step-by-step choreography ships as four companion skills (and matching Goose recipes) in this repo: marmot-group-setup, marmot-relay-strategy, marmot-encrypted-media, and marmot-push-notifications. Each one orchestrates the Nostr events and delegates every cryptographic operation to MDK / marmot-ts — never reconstructing MLS by hand.

Use the Build Studio to assemble the stack — pick your language (Rust via MDK, or TypeScript via marmot-ts), add the catalog entries above, and export a Goose recipe. Then run it in your own Goose, on your machine, with your own model and keys. The platform hands Goose a recipe; it never sees your keys or your messages.

Both Nostr (Marmot) and AT Protocol (Germ-style) approaches inherit MLS’s forward secrecy and post-compromise security. The real decision is about transport, ecosystem, and maturity — match it to your threat model, not to hype.

  • Your users’ identities already live on Nostr; you value censorship-resistance and no phone/email.Marmot / White Noise (Nostr). You get decentralized relays you choose and Nostr-native identity. Accept that it’s experimental and capped at ~150-member groups for now.
  • Your users live on AT Protocol / Bluesky and you want E2EE there. → the AT Protocol path (e.g. Germ’s lexicon). This is an even earlier, separate ecosystem — and again, not wire-compatible with White Noise.
  • You need audited, production-grade E2EE today, and decentralization is secondary. → Be honest with yourself and your users: a formally-audited messenger is the safer choice right now. Come to Marmot to build and contribute, or when decentralization and Nostr identity outweigh maturity.
  • Browse the verified building blocks in the catalog.
  • Stand up your harness with Get started with Goose.
  • Read the protocol itself: Marmot (and its MIPs), pinned at commit 21a67b2.