The Messages and Groups chapter explained how messages are encrypted and prepared for MLS groups before they are given to the delivery service, which handles getting them to mailboxes.
Since MLS is the layer responsible for ensuring the confidentiality and integrity of messages, mailboxes are purely concerned with delivery and metadata, and used to secure access to ciphertext rather than the contents of the messages.
This chapter talks about how messages behave in transport, covering personal and group mailboxes, how keys are derived for each, and mailbox encryption.
Overview
Rhizo uses two mailbox types plus one queue to fulfill Delivery Service duties:
| Component | Purpose |
|---|---|
| Group mailbox | Strictly-ordered delivery to a group |
| Personal mailbox | 1:1 delivery to a single recipient |
| Queue | Publishes key packages so others can add you to a group |
As the server chapter explains, the server is intentionally designed to know as little as possible. Its main job is to host mailboxes and verify keys. If a key checks out, it releases the data, and doesn’t perform any logic beyond that authorization check.
Mailbox key seed
All keys used in the mailbox system are derived from MailboxKeySeed. It’s 32 bytes long value, derived from the MLS Group secret using Exporter, for the mailboxes used for group message delivery. This means that every key seed is tied to a specific Group Epoch and rotates together with said epoch.
The key seed is contextualized per recipient if appropriate (e.g. when using personal mailboxes).
Group mailboxes
Group mailboxes serve messages to the group as a whole.
Access to the mailbox for reading and sending messages is gated through GroupMailboxKeypair. This key pair is derived through HKDF directly from the key seed described above.
The group mailbox address is the public key of the mailbox’s key pair.
The server enforces strict message sequencing here. This is why commits specifically go through the group mailbox rather than personal-mailbox fan-out — it’s the simplest way to guarantee the group can’t fork.
Messages are pruned after a fixed expiration window. Since the server doesn’t know group membership size or read status of each member, messages can’t be deleted on confirmation of receipt.
Personal mailboxes
Personal mailboxes are the mechanism for client-side fan-out, as well as sending over the welcome messages directly to invited member. They are modeled like a postbox: the sender (Delivery Service, or the postman) drops something in, and only the recipient is supposed to be able to take it out.
Access to this mailbox is controlled through two different keys:
- Write key pair — key needed to send message to someone’s mailbox. Any group member can derive this directly via HKDF from the mailbox key seed. Not sender-restricted — anyone in the group can write to anyone’s personal mailbox for that group.
- Read key pair — key needed to read from a mailbox. Derivation of this key is where the asymmetry between sender and recipient lives (as we use HDKD).
To derive the keys, members use the MailboxKey published on the mailbox owner’s identity chain.
- From a public mailbox key (the one published on-chain), anyone can derive the public read key for the mailbox.
- Only the corresponding private mailbox key holder can derive the mailbox’s private read key (via HDKD).
Every group member can derive secret write key and the public read key for everyone else, but only the recipient can ever produce the private read key for their own mailbox.
The mailbox is addressed by the tuple of public keys from both key pairs.
Since this mailbox is used by a single client, this allows it to be purged immediately after the recipient downloads a message. Nobody else needs continued access to it, and doing this hides how many messages have passed through the mailbox over time.
Queue
The queue is used to publish your key packages so others can discover and use them to add you to a group.
The queue is structurally similar to personal mailboxes, but uses a single key pair — the KeyPackageQueue key pair — derived through HDKD, in the same fashion that personal mailbox read keys are. Where only you can derive private key, while public key for the queue can be derived by anyone in the space.
Private key is used to upload key packages to the queue, while public key is used to get them from the queue. This means that only you can upload key packages to your queue, but anyone can download them.
Key packages are deleted from the queue the moment someone fetches them, as they are single use.
Mailbox encryption
All messages in Rhizo are encrypted twice:
- Once by MLS itself, using the group’s normal MLS encryption mechanism.
- Once more using a key derived from the mailbox key seed, specifically for the mailbox it’s sent to.
We do not do this to improve strength of the ciphertext, but as an anti-correlation method.
With client-side fan-out, the same message is sent out multiple times (once per recipient device/mailbox). If every copy used the same MLS ciphertext, an outside observer could correlate those copies. They could tell that N copies of a fanned-out message are the same, and infer group membership or messaging patterns. Re-encrypting each copy with a distinct, mailbox-specific key prevents that correlation.
Given that message content is protected by MLS, we pay a lot of attention to preventing metadata leakage as much as it is practically possible.