Inside Marmot: Six Specs That Make Private Group Messaging Work

Inside Marmot: Six Specs That Make Private Group Messaging Work

The Marmot Protocol is an open specification for encrypted group messaging built on Nostr and the MLS cryptographic protocol. Its design is documented across six Marmot Implementation Proposals, MIP-00 through MIP-05, each defining a layer of the system. Four are mandatory for any compatible implementation. Two are optional extensions. Together they describe how a group of people can communicate privately over a decentralized network without trusting any single server or exposing the fact that they are talking to each other at all. What follows is a walkthrough of each spec and why it matters to you as a user.

MIP-00: Your Invitation Card

Every messaging system begins with identity, and MIP-00 defines how Marmot handles yours. The foundation is your Nostr keypair, the same cryptographic identity you already use across Nostr clients. Marmot links that identity to a separate MLS signing key that authenticates your messages within encrypted groups. The separation is deliberate: if someone compromises your group signing key, your Nostr identity remains untouched.

The spec introduces KeyPackages, which function as public invitation cards. When you want to be discoverable for group invitations, you publish a KeyPackage event (kind 443) to Nostr relays. This event advertises your cryptographic capabilities and an ephemeral public key that others can use to encrypt a group invitation specifically for you. Think of it as leaving your business card at the front desk so colleagues can reach you without needing your home address.

KeyPackage management is where MIP-00 gets careful. Each KeyPackage contains an init_key, an ephemeral HPKE public key whose corresponding private key sits only on your device. Once you use that key to join a group, the spec requires your client to securely delete the private key material from memory and disk. This is forward secrecy at the invitation layer: even if an attacker later compromises your device, captured KeyPackages from the past cannot be decrypted to reveal which groups you were invited to. The spec also supports a "last resort" KeyPackage for handling race conditions when multiple invitations arrive simultaneously, though even these should be rotated regularly.

Signing key rotation rounds out the picture. Members should periodically update their signing keys within each group they belong to, limiting the damage from any single key compromise. MIP-00 does not prescribe a rotation schedule, leaving that decision to client implementations, but the expectation is clear: stale keys are a liability.

MIP-01: Building the Room

With identities established, MIP-01 defines how groups are constructed. Every MLS group gets a unique 32-byte identifier that is never published to relays. This privacy guarantee matters because the identifier itself could reveal the existence and timing of group creation to an observer monitoring relay traffic.

Before creating a group, a client must verify that all intended members support compatible cryptographic parameters by checking their published KeyPackages. This compatibility check prevents the frustrating scenario where someone gets invited to a group their client cannot decrypt. The group creator then establishes the initial MLS state, setting up the ratchet tree that will manage cryptographic keys as members join and leave.

The centerpiece of MIP-01 is the Marmot Group Data Extension, a custom MLS extension carrying Nostr-specific metadata inside the cryptographically authenticated group state. This extension stores the group name and description, admin public keys, relay preferences for message distribution, and encryption parameters for the group avatar image. Because this data lives inside the MLS group context, any modification requires a valid MLS Commit signed by an authorized admin. An attacker who compromises a relay cannot forge a group name change or inject a fake admin key. The cryptographic authentication runs end-to-end, from the admin who proposed the change through every member who verifies it.

The group image encryption in MIP-01 deserves a note because it illustrates the spec's thoroughness. Group avatars are encrypted with ChaCha20-Poly1305 using keys derived through HKDF from seeds stored in the extension, then uploaded to Blossom storage servers as opaque encrypted blobs. The upload authentication uses a separate keypair derived from an independent seed, ensuring that the encryption key and the upload credential are cryptographically isolated. When an admin changes the group image, the old image can be deleted from storage because any admin who witnessed the previous extension state can derive the old upload keypair and request deletion.

MIP-02: Getting Through the Door

Creating a group means nothing if people cannot join it. MIP-02 defines Welcome Events (kind 444), the mechanism through which new members receive everything they need to participate: group secrets, current member state, the ratchet tree structure, and all active extensions including the group metadata from MIP-01.

The spec wraps Welcome Events in NIP-59 gift wrapping, a Nostr privacy technique that hides both the sender and recipient of a message from relay operators. The inner Welcome event is deliberately unsigned so that if it somehow leaks, it cannot be published to a public relay (most relays reject unsigned events). This is defense in depth: the gift wrapping provides privacy, and the unsigned construction provides damage control.

Timing is critical, and MIP-02 is emphatic about it. The admin who adds a new member must wait for relay confirmation that the associated Commit message has been accepted before sending the Welcome. Without this sequencing, a state fork can occur: the new member activates at a group epoch that existing members have not reached yet, and messages become mutually undecryptable. In a centralized system this ordering is trivial because a single server enforces it, but in Nostr's distributed relay network, messages can arrive out of order across different relays. MIP-02 solves this by making the admin responsible for waiting.

After joining, new members should perform a self-update as soon as possible, generating fresh key material that was never published or observable on any relay. The spec recommends completing this update before sending any messages, and requires it within 24 hours. Until the self-update completes, the member's key material is the same as what was in their KeyPackage, which was publicly available on relays. Rotating immediately closes that exposure window.

MIP-03: Talking and Governing

MIP-03 is the workhorse of the protocol, defining Group Events (kind 445) that carry all group communication: control messages for managing the group, and application messages for the actual conversations.

Every Group Event is encrypted with ChaCha20-Poly1305 using a key derived from the MLS exporter secret for the current epoch. The encryption key remains stable for an entire epoch, so nonce uniqueness becomes the sole protection against keystream reuse. The spec requires cryptographically random 12-byte nonces for every event and mandates that if the random number generator fails, the encryption operation must abort entirely. There is no fallback and no deterministic alternative. If you cannot generate a proper nonce, you do not send the message.

Each Group Event is published using an ephemeral Nostr keypair generated fresh for that single event, meaning that an observer watching relay traffic cannot link two messages to the same sender. The only visible identifier is the group's Nostr group ID in the h tag, which tells relays where to route the message but reveals nothing about who sent it.

Group governance operates through a proposal and commit system. Any member can propose changes: adding someone, removing someone, updating group settings. But only admins can commit those proposals into the group state, with one exception. Any member, regardless of admin status, can perform a self-update Commit that rotates their own key material. This design prevents a situation where a non-admin user cannot maintain their own forward secrecy because they lack permission to touch the group state.

When competing Commits arrive for the same epoch (because two admins acted simultaneously without knowledge of each other), the spec resolves the conflict deterministically: pick the Commit with the earliest timestamp, and break ties by choosing the lexicographically smallest event ID. All clients apply the same rule, so everyone converges on the same group state without coordination.

Inside the encrypted envelope, application messages use standard Nostr event formats: kind 9 for chat messages and kind 7 for reactions, among others. These inner events carry the sender's real Nostr pubkey for identity verification but remain unsigned to prevent leakage. If a decrypted inner event were somehow extracted and published to a public relay, the lack of a signature would make it unverifiable and therefore unpublishable on most relays.

MIP-04: Sharing Files Privately

MIP-04 extends the protocol to handle media: images, videos, audio, documents, anything you might want to share within a group conversation. The approach is simple: encrypt the file, store the encrypted blob on a content-addressed storage system like Blossom, then share the metadata through the group's encrypted channel.

The encryption key for each file is derived deterministically from the MLS exporter secret combined with the file's SHA-256 hash and its MIME type plus filename. This means the key is unique to both the file and the current MLS epoch, providing forward secrecy for media. The nonce, by contrast, is generated randomly for each encryption operation and stored in the imeta tag alongside the file URL and the original file hash. The spec learned from an earlier mistake: version 1 used deterministic nonce derivation, which created a vulnerability when the same file was encrypted multiple times with the same metadata. Version 2 fixed this by switching to random nonces, and the spec now requires clients to reject version 1 tags entirely.

Content-addressed storage provides an extra layer of privacy. The storage address is the SHA-256 hash of the encrypted content, which is effectively random from the perspective of anyone who does not hold the decryption key. A storage server cannot correlate encrypted blobs with their original files and cannot even tell whether two different encrypted blobs contain the same original content, because different epochs produce different encryption keys.

The spec deliberately limits its scope to single-blob encryption. Chunked encryption for large files and streaming decryption for progressive loading are explicitly out of scope for version 2. These features introduce complexity that the spec authors chose to defer until the simpler case is proven solid.

MIP-05: Notifications Without Surveillance

Push notifications are the privacy hole that most encrypted messengers ignore. Your messages may be mathematically secure, but the push notification that woke your phone still traveled through Apple or Google's infrastructure, logging the fact that you received a message from a particular app at a particular time. For governments, that metadata can be more valuable than message content.

MIP-05 accepts that Apple and Google's push services are unavoidable on mobile devices but removes the need to trust the notification server with anything meaningful. The mechanism is elegant: your device token (the identifier Apple or Google uses to reach your phone) is encrypted with the notification server's public key using an ephemeral keypair generated specifically for that encryption. The server can decrypt the token and forward the notification, but it cannot link the encrypted token to your Nostr identity or correlate tokens across groups to determine which ones belong to the same user.

Payload padding ensures that all encrypted tokens are exactly 280 bytes regardless of platform, preventing group members from inferring whether someone uses iOS or Android based on token size. Decoy tokens from other groups are mixed in with real ones when triggering notifications, obscuring group sizes and preventing the server from building social graphs by observing which tokens are bundled together.

The notification trigger itself uses NIP-59 gift wrapping with layered ephemeral keys: the inner rumor event and its authenticating seal share one ephemeral key, while the outer gift wrap uses a separate ephemeral key entirely. The notification server sees a stream of identically structured encrypted events arriving at its inbox relays and can extract device tokens from them, but it cannot determine who sent them, which group they came from, or how many real recipients are hidden among the decoys.

Token distribution among group members uses a gossip protocol carried inside the encrypted MLS channel. When you join a group, you broadcast your encrypted token along with a request for other members' tokens. Members respond with their complete token lists, and passive observation of all token messages lets everyone converge on a consistent view without central coordination. When members leave, their tokens are automatically purged.

The spec includes a thoughtful prohibition against using Firebase Cloud Messaging as a proxy for iOS devices. If all platforms routed through FCM, Google could correlate users across iOS and Android and across groups, defeating the probabilistic encryption that prevents cross-group tracking. iOS must use APNs directly.

What This Means for Users

The six MIPs form a complete system. The first gives you a portable identity tied to your Nostr keys, and the second lets you form groups with cryptographically enforced governance. New members get in safely through MIP-02's Welcome mechanism, while MIP-03 handles all communication with forward secrecy and sender unlinkability. Encrypted media follows from there, and the final spec ensures that even the notification layer, the part where most encrypted messengers quietly surrender your metadata, reveals nothing worth knowing.

The protocol requires no phone number and no email address. Your identity is your Nostr keypair, and your participation in any group is invisible to everyone outside that group. Relay operators see encrypted blobs tagged with group identifiers but cannot read the content or identify the sender. Storage servers hold encrypted files they cannot decrypt. Notification servers forward push alerts they cannot attribute. Every layer of the stack is designed so that the infrastructure operators learn the minimum information required to perform their function and nothing more.

Marmot is still experimental. The specs are under active review and a formal security audit has been completed. The architecture is coherent, and the cryptographic foundations are sound: MLS is an IETF standard with years of academic scrutiny behind it, and working implementations already exist in both Rust (MDK) and TypeScript (marmot-ts). For anyone who has been waiting for group messaging that takes privacy seriously from the protocol layer up, the specifications are worth reading and the software is worth trying.