Skip to main content

🔧 Managing the Room

Group Operations in MLS

In 15 minutes: Learn to manage MLS groups end-to-end


🎯 What You'll Learn

Creating, modifying, and maintaining MLS groups:

OperationFunctionComplexity
Create groupcreateGroup()O(1)
Add memberaddMembers()O(log n)
Remove memberremoveMembers()O(log n)
Update keyupdateKey()O(log n)

🎨 Operation Overview


📝 Complete Flow Example

// ==========================================
// 1. INITIALIZATION (Both users)
// ==========================================

const alice = new MLSManager('alice@example.com');
await alice.initialize();
const aliceKeyPackage = await alice.generateKeyPackage();

const bob = new MLSManager('bob@example.com');
await bob.initialize();
const bobKeyPackage = await bob.generateKeyPackage();

// Share key packages (transport layer)
// aliceKeyPackage.publicPackage → bob
// bobKeyPackage.publicPackage → alice

// ==========================================
// 2. CREATE GROUP
// ==========================================

await alice.createGroup('meeting-room');
// Alice now: epoch 0, group secret K₀

// ==========================================
// 3. ADD BOB
// ==========================================

const { welcome, commit } = await alice.addMembers('meeting-room', [{
publicPackage: bobKeyPackage.publicPackage,
userId: 'bob@example.com',
}]);

await alice.processCommit('meeting-room', commit);
// Alice now: epoch 1, group secret K₁

// Send welcome to Bob (transport layer)
// await sendWelcomeToBob(welcome);

// Bob receives and joins
await bob.processWelcome(welcome);
// Bob now: epoch 1, group secret K₁

// ==========================================
// 4. SEND MESSAGES
// ==========================================

// Alice sends
const envelope1 = await alice.encryptMessage('meeting-room', 'Hello Bob');

// Bob receives + decrypts
const msg1 = await bob.decryptMessage(envelope1);
console.log(msg1); // Hello Bob

// ==========================================
// 5. ADD CHARLIE
// ==========================================

const charlie = new MLSManager('charlie@example.com');
await charlie.initialize();
const charlieKeyPackage = await charlie.generateKeyPackage();

const { welcome: welcome2, commit: commit2 } =
await alice.addMembers('meeting-room', [{
publicPackage: charlieKeyPackage.publicPackage,
userId: 'charlie@example.com',
}]);

await alice.processCommit('meeting-room', commit2);
await bob.processCommit('meeting-room', commit2);
await charlie.processWelcome(welcome2);

// ==========================================
// 6. GROUP MESSAGES
// ==========================================

// Charlie sends
const envelope2 = await charlie.encryptMessage('meeting-room', 'Hi everyone');

// Alice + Bob decrypt
const msg2 = await alice.decryptMessage(envelope2);
const msg3 = await bob.decryptMessage(envelope2);
console.log(msg2); // Hi everyone

🎯 Key Package Exchange

How to share key packages:

// Using a server (recommended)
await fetch('/key-packages', {
method: 'POST',
body: JSON.stringify({
userId: 'alice@example.com',
publicKeyPackage: aliceKeyPackage.publicPackage
})
});

// Using P2P signaling
await signal.send('key-package', aliceKeyPackage.publicPackage);

// Using email
await email.send({
to: 'bob@example.com',
subject: 'My MLS Key Package',
attachment: aliceKeyPackage.publicPackage
});

✅ Quick Check

Question 1

Alice creates group epoch 0 (K₀). She adds Bob. What's the epoch after commit?

Answer: Epoch 1 (new group secret K₁)


Question 2

Bob receives welcome and joins group epoch 1. Can he read epoch 0 messages?

Answer: No (forward secrecy - K₀ deleted)


🎓 Summary

createGroup = Start with 1 member
addMembers = Commit + welcome
processCommit = Update group state
processWelcome = Join as new member
encryptMessage = Send to group
decryptMessage = Receive from all members