🔧 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:
| Operation | Function | Complexity |
|---|---|---|
| Create group | createGroup() | O(1) |
| Add member | addMembers() | O(log n) |
| Remove member | removeMembers() | O(log n) |
| Update key | updateKey() | 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