Skip to content

Instantly share code, notes, and snippets.

@Bren2010

Bren2010/mimi.md Secret

Created March 26, 2024 18:36
Show Gist options
  • Save Bren2010/d009ba8d702ae3428b31981295455f02 to your computer and use it in GitHub Desktop.
Save Bren2010/d009ba8d702ae3428b31981295455f02 to your computer and use it in GitHub Desktop.
MIMI Delivery Service

This document describes a federated MLS Delivery Service (DS) for use in the More Instant Messaging Interoperability (MIMI) protocol. The DS provides for the delivery of KeyPackages, Welcome messages, and group handshake/application messages.

Abbreviations

  • Local Service Provider (LSP): The Service Provider preferred by the referenced user.
  • Remote Service Provider (RSP): Any Service Provider used by a user which is not the hub or the LSP.

Data Consistency Model

  • The "hub" is the Service Provider which created a group.
  • Group messages / Welcome messages are sent to the hub for sequencing and fanout.
  • Only Welcome messages are pushed to RSPs without solicitation. If pushing a Welcome to any RSP fails, the associated Commit is rejected and an error is propagated to the client.
  • Group messages may be pulled by RSPs, or RSPs may opt into having new messages pushed. The RSP must provide the group ID to receive messages for a group.

Example flow: A single user creates a group with several outside users and triggers their LSP to push a Welcome to an RSP. If any of the RSP's users accept the Welcome, they trigger the RSP to pull the group messages. The RSP's users send messages which are pushed to and sequenced by the hub.

Discovery

It's assumed that users have already interacted with a Discovery Service to learn the user ID and preferred Service Provider of their contacts. As part of discovery, users also receive a bearer token associated with each contact. The bearer token may or may not be unique to the user who requested it, depending on the RSP's preference.

KeyPackages

Users that wish to add members to a group need to fetch KeyPackages for those members. A user can fetch KeyPackages by issuing OHTTP requests through its LSP to each RSP. A single KeyPackage request contains:

  1. The bearer token learned during discovery, which is used for authentication and spam mitigation.
  2. The user ID to return a KeyPackage for.

The request is authenticated solely by the bearer token. Depending on the user's preference, KeyPackage requests for different users of the same Service Provider may be either batched or issued individually.

KeyPackage LeafNodes contain an extension indicating basic compatibility information about the user's devices and Service Provider, including: the max group size, and a policy for when they expect handshake messages to be encrypted or unencrypted.

Welcome messages

Once all KeyPackages have been fetched, the user provides the following to its LSP:

  1. The Commit message and other metadata (see next section).
  2. The Welcome message.
  3. A map indicating which KeyPackageRef belongs to which RSP.

If the LSP is not the hub, it forwards this information to the hub.

The hub contacts each RSP and lists the KeyPackageRefs that have been indicated as belonging to its users. The RSP responds affirmatively if it recognizes all KeyPackageRefs, which triggers the LSP to send the Welcome message and optional GroupInfo.

Group Messages

A user that receives a Welcome and wishes to participate in the group informs its LSP of the group ID. The LSP contacts the hub (the Service Provider from which it received the Welcome) and attempts to pull messages related to the group.

When a user wants to send a group message, it provides the following to its LSP:

  1. The MLSMessage, containing a PublicMessage or PrivateMessage.
  2. If the message is a Commit, an optional GroupInfo struct (which is only provided when the corresponding Commit initializes an epoch with unencrypted handshake messages, based on the aggregated policy of members' LeafNodes)

If the LSP is not the hub, it forwards this information to the hub. The hub sequences the message and supports fanout.

A hub will accept group messages from any RSP that knows the group ID. Similarly, a Service Provider will allow any user that knows a group's ID to message that group. Even if handshake messages are unencrypted, providers should not attempt to enforce access control policies stronger than this, as they are unable to verify the correctness of Commits changing group membership.

Partition Keys

A partition key is a short secret exported from the MLS key schedule. Whenever users send or receive group messages, they provide the partition key for the current epoch. Messages sent with a given partition key are only provided to users who request to receive messages with the same partition key. (Exceptions may be selectively made for external commits / proposals, given that the sender isn't in the group yet.)

The partition key acts as epoch-level access control, in addition to the group ID. Users which have been removed from a group may still be able to message the group, as they know the group ID. However, they will not know the correct partition key.

Service Providers should not implement hard-and-fast rules about which partition keys are acceptable. Instead, it should be considered as a general signal of abuse or spam.

Et cetera

A Service Provider that uses the unencrypted handshake messages of a group to attempt to infer the group state MUST give users the ability to override the inferred state when publishing a Commit if it is incorrect. Similarly, for Commits published by RSPs, the LSP must defer to the GroupInfo and ratchet tree published by the RSP.

Self-removal doesn't have any special protocol consideration. A user that no longer wishes to participate in a group sends a Remove proposal for themself and informs their Service Provider they're no longer interested in receiving the group's messages. A Service Provider with no users interested in a group simply stops pulling the group's messages.

I would also require virtual clients / subgroups to be used to simplify the protocol (one leaf per user).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment