Implementation Overview
Thexmtp_mls crate uses OpenMLS as the underlying MLS implementation, adding XMTP-specific validations and extensions.
Core Responsibilities
An XMTP MLS client manages:- Network connections through an API client
- Local SQLite database for state and messages
- MlsProvider for OpenMLS cryptographic operations
- Message and identity authentication according to XMTP rules
MLS Configuration
Ciphersuite
LibXMTP uses a single ciphersuite for all groups:- Key Exchange: X25519 for ECDH
- AEAD: ChaCha20-Poly1305 for symmetric encryption
- Hash: SHA-256
- Signatures: Ed25519 for message authentication
Signature keys are not rotated since the public key forms a persistent identity for the installation.
Group Parameters
Groups are created with these OpenMLS parameters (fromgroups/mod.rs:1218-1225):
- Maximum past epochs: 3 (lower than OpenMLS default of 5)
- Maximum forward ratchets: 1000 (OpenMLS default)
- Wire format: Private messages only (maximum metadata hiding)
Secret Tree and AEAD
XMTP uses the MLS secret tree with AEAD for encrypting application messages. This provides:- Per-sender key derivation: Each sender has independent ratchet chains
- Forward secrecy: Keys are deleted after use
- Out-of-order delivery: Messages can be decrypted independently
Client Lifecycle
Initialization
When initializing a new client with a fresh database:- SDK generates a new installation private key (Ed25519)
- Key is stored in local SQLite database
- Subsequent instantiations reuse this key
Installation Registration
Before creating or joining groups, the client must link installation keys to an XMTP Inbox. Three scenarios exist:1. New Inbox (no registration exists)
The client:- Generates an identity update with
CreateInbox+AddAssociationactions - Signs with installation keys
- Requests wallet signature from application
- Uploads signed key package and identity update
- If accepted, ready to send/receive messages
For
nonce=0 with XMTP V2 keys available, CreateInbox can be signed with V2 keys instead of the wallet (one-time migration).2. Existing Inbox, New Installation
The client:- Generates
AddAssociationidentity update - Signs with installation keys
- Requests signature from any wallet already linked to inbox
- Uploads signed key package and identity update
3. Existing Registration
Client is immediately ready; no additional signatures or uploads needed.Key Packages
Structure
Each client maintains a key package containing:- Installation public key (Ed25519) in the credential
- HPKE init key (ephemeral X25519)
- Lifetime and supported capabilities
- Signature over the package
Validation
When validating another user’s key package:- Perform standard MLS validations (signature, authenticity)
- Validate installation key is associated with the
inbox_idin the credential - Download latest identity updates for the inbox
- Ensure installation key is present and not revoked
Rotation
Clients rotate key packages:- After receiving a welcome message (package was consumed)
- Can batch rotation if receiving N welcomes at once
- Keep at most 2 HPKE keypairs (current + previous)
Group Operations
Creating a Group
- Group has one member (creator’s installation)
GroupMembershipextension maps creator’sinbox_idtosequence_id=0- Creator is the only
super_admin - First action on group updates creator’s
sequence_id, adding other installations
Sync Welcomes
Clients poll for welcome messages:- Outer HPKE decryption: Uses
hpke_init_keyfrom recipient’s key package - Inner MLS welcome: Standard TLS serialized MLS welcome
- Validation: Ensure members match expected installations per
GroupMembership - Welcome contains ratchet tree (no additional queries needed)
Welcome messages have two layers of encryption. The outer HPKE layer makes multiple welcomes unlinkable on the server.
Key Rotation in Groups
Group members update their path encryption secret:- Before sending first message to the group
- Before sending, if 3 months elapsed since last path update
Validation
LibXMTP performs two validation levels:MLS Protocol Validation (OpenMLS)
Standard MLS checks:- Signature verification
- Epoch consistency
- Proposal validation
- Tree math correctness
Application-Level Validation (LibXMTP)
Commit Validation
For each commit:- Ensure allowed by group permission policies
- Validate credentials and key packages of new members
- Ensure MLS membership changes match
GroupMembershipextension diff
Credential Validation
The MLS credential contains a single field:inbox_id. To validate:
- Resolve the association state for that inbox (via XIP-46)
- Ensure installation key signing the credential is a current member
XMTP does not implement credential rotation because they represent a long-lived connection between the MLS client and the inbox.
Revocation and Recovery
Installation Revocation
Installations/wallets may be revoked by publishing aRevokeAssociation identity update (XIP-46).
Clients periodically check for revocations during sync, so removals typically happen quickly, but the protocol makes no timeliness guarantees.
Inactive Clients
XMTP does not automatically detect or remove inactive clients. Applications must:- Detect inactivity at the application level
- Trigger manual removal of inactive installations
Extensions
Required Extensions
XMTP uses theseGroupContextExtensions in every MLS group:
-
GroupMembers: List of inbox IDs and their currentsequence_id- Governed by
add_member_policyandremove_member_policy
- Governed by
-
GroupMutableMetadata: User-defined metadata (name, description, etc.)- Changes governed by
update_metadata_policy - Admin list changes governed by
add_admin_policy/remove_admin_policy
- Changes governed by
-
GroupMutablePermissions: Current permission policies- Changes governed by
update_permissions_policy
- Changes governed by
Authentication Service
Per RFC 9420 Section 5.3.1, an Authentication Service (AS) links public keys in leaf nodes to users. XMTP implements a direct binding instead of a separate AS:- Inbox ID is directly bound to the signature key in leaf nodes
- Validation done via XIP-46 association state
Delivery Service
The Delivery Service (DS) transports messages and key packages between clients.XMTP Implementation
XMTP uses a central server with:- No special permissions required (IP rate-limited for spam)
- APIs for submitting and reading:
- MLS-encrypted chat messages (by group ID)
- Welcome messages (by installation key)
- Messages returned in order received
- Reading does not change server state
Welcome Message Privacy
Welcomes have an additional HPKE encryption layer applied client-side:- When creating a commit with multiple Add proposals, welcomes share content
- Without extra encryption, observers could link users added to the same group
- HPKE encryption makes welcomes unlinkable
Decryption Failures
If decryption fails:- SDK drops the message
- Telemetry notifies developers of failures
- Currently no fork detection or recovery mechanism
- DoS attack (spam)
- Group state divergence (SDK or OpenMLS bug)
Security Properties
Provided Guarantees
MLS with XMTP’s configuration provides:- Privacy: Message content hidden from non-members
- Authenticity: Messages verifiably from claimed sender
- Forward Secrecy: Past messages safe if keys compromised
- Post-Compromise Security: Future messages safe after key refresh
Not Protected Against
- Physical attacks on endpoints
- Network privacy (IP addresses visible)
- Message deniability
- Membership privacy (inherited from MLS)
- Ciphertext size analysis
- Quantum adversaries (no post-quantum ciphersuite standardized yet)
With #1851, LibXMTP provides Harvest Now Decrypt Later (HNDL) forward security.
Transport Security
Per MLS architecture Section 8.1, transport channels should hide metadata. XMTP uses gRPC with TLS via Rustls. Since XMTP uses private messages everywhere (maximum metadata hiding), minimal metadata leaks even without transport-level protection.Related Concepts
- Identity System - Wallet and installation associations
- Groups and Conversations - Group management
- Client Lifecycle - Initialization and registration
