From a6a24f3d12c95db1c4c6def45a693e26ac1491fb Mon Sep 17 00:00:00 2001 From: Benjamin Beurdouche Date: Thu, 19 Dec 2024 13:24:28 +0100 Subject: [PATCH 01/24] Initial draft of MLS explainer --- MessagingLayerSecurity.md | 569 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 569 insertions(+) create mode 100644 MessagingLayerSecurity.md diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md new file mode 100644 index 0000000..8577896 --- /dev/null +++ b/MessagingLayerSecurity.md @@ -0,0 +1,569 @@ +# Explainer: Prototype Web API for Messaging Layer Security (MLS) + +[Benjamin Beurdouche](mailto:bbeurdouche@mozilla.com) +Last updated: November 29, 2024 + +### Overview + +This document describes a Web API for the Messaging Layer Security (MLS) +protocol (RFC 9420). MLS provides group key exchange for changing groups, which +enables secure communication within those groups. + +### Problem statement + +For the longest time, due to the lack of technology, pairwise channels were used +to communicate between two principals (actors of a protocol) and a lot of +additional complexities had to be paid by the Applications on top of the +pairwise channels to build Groups. In particular changing the set of +participants in groups securely was impractical without a significant amount of +expertise and security review. + +In most cases those custom group protocols were not well (if at all) specified +nor formally analyzed. Most of the security guarantees provided by strong +pairwise channels are broken by applications in non-trivial ways because those +typically don’t provide group agreement (everyone has the same view of the group +and its secrets) or even the correct notion of authentication or secrecy. +Performance was also a concern as the computational complexity of creating +groups or sending messages based on pairwise channels is quite high (O(N^2)) and +incompatible with large dynamic groups. + +We aim at solving this issue in the Web Platform by following the WebRTC example +and provide a way for Applications to build evolving groups of participants. +This enables applications for **secure group communication** including +video-conferencing (SFrameTransform for WebRTC, Media Over QUIC,...), secure +messaging (RCS, MIMI), encrypted cloud storage, and more. + +### Proposal + +Messaging Layer Security (MLS) (RFC 9420) provides convenient and secure +***Continuous Group Key Agreement (CGKA) for dynamic groups***, ranging from one +to hundreds of thousands of participants. + +The MLS API provides applications with two main capabilities: + +* Group management: applications can manage the participation of different +* entities, including the current browser, in groups. + +* Secure messaging: once +* created, a group generates a shared secret that can be used to provide +* end-to-end protected messaging with group participants. + + This explainer outlines the goals, design, and potential use cases of the API. + +### Goals + +1. **Provide a Continuous Group Key Agreement**: We want to enable Web and +Internet applications to use MLS as a way to build and manage groups using its +secure group key establishment directly from the browser, in particular for +End-to-End Encrypted applications. + +2. **State-of-the-Art Security**: Manipulate sensitive values and cryptographic +secrets of the protocol natively instead of exposing them to the web +application. Shipping an up-to-date MLS library which removes the need for +application developers to have a dedicated evaluation and software lifecycle for +this critical component. Similar to TLS, QUIC or WebRTC, ensure to provide a +high quality implementation to users. + +3. **Privacy and avoid user tracking**: Prevent user tracking by using +traditional techniques of partitioning the MLS state by origin. This will ensure +that strong identifiers like public keys are not reused across sites. + +4. **Ensure Performance**: Avoid back and forth between JavaScript, C++, storage +and cryptographic computations. Handle everything natively within browser native +code. + +### Non-Goals + +1. **Expose all possible MLS functionality**: The MLS protocol does not +currently have a “standard” API as it can be used in many different ways. We +will provide a significant subset of all these possibilities starting with safe +defaults and will listen for feedback in case extensions are requested by +developers. + +2. **Guarantee full interoperability across applications**: We cannot force that +different applications are interoperable, especially in a federated +context. However if service providers decide to agree on interoperability at the +application level by defining coherent MLS group and client configurations, the +MLS layer messages will be interoperable and applications will be able to build +a shared group. + +### How do I enable the experiment ? + +**Navigate to \`about:config\` and set \`security.mls.enabled\` to \`true\`.** + +### Terminology + +A few key concepts of the MLS protocol that are necessary to understand the API. + +**Identities and Credentials** + +The client is a participant in the protocol which is owned by users. Each +client, whether it is part of a group or not, has a unique identity or client +identifier which is a handle to a signature keypair. Each client can be +associated with a credential which is a way to reflect additional information +related to the identity. The default API offers a facility to create +credentials containing arbitrary strings called basic credentials but X509 or a +verifiable credential can be generated externally and be used in the API. + +**Key Package** + +In order for users to add clients to a group, those need to +produce some encryption public key and some metadata about the ciphersuite and +extension they support for that client. This information is called a key +package. By default the API contains a function to generate those key packages +with the default parameters and extensions supported by the implementation in +Firefox. + +**Groups and GroupViews** + +Since the goal of MLS is to build and manage groups, the API is centered about +the notion of group and in particular of the GroupView object which represents +the view of a group for a specific client. The reason for this is that it is +allowed to have multiple clients in a group as long as they have different +client identifiers. Though it is an advanced feature, if multiple clients are +used in the same group, each client is able to manage its view of the group and +may process messages at different times. Each time the group evolves, a sequence +number called epoch is incremented. + +**Proposals and Commits** + +Group operations such as adding or removing users can be either proposed by +generating a proposal or the change can be made directly by generating a commit +output. Each commit output contains some information, when adding a user, it +contains a commit message, which is the information that needs to be transmitted +to existing members of the group, and a welcome message which is the information +that needs to be transmitted to the newly added client. + +### Basic usage + +```javascript +let mls = new MLS() + +// Create identities for alice and bob +let a = await mls.generateIdentity() +let b = await mls.generateIdentity() + +// Create credentials for alice and bob +let ac = await mls.generateCredential("alice") +let bc = await mls.generateCredential("bob") + +// Create key packages for alice and bob +let akp = await mls.generateKeyPackage(a, ac) +let bkp = await mls.generateKeyPackage(b, bc) + +// Bob creates a group +let gb = await mls.groupCreate(b, bc) + +// Bob adds Alice to the group by using the Key Package +// (this generates a commit output which contains the welcome necessary +// to alice and the commit to update current members of the group) +let co1 = await gb.add(akp) + +// Bob uses the generated commit to update its group and immediately +// sends a message to the group (alice, bob) +let bgide1 = await gb.receive(co1.commit) +let ctx1 = await gb.send("Hello Alice!") + +// Alice uses the welcome to join the group and receives Bob's message +let ga = await mls.groupJoin(a, co1.welcome) +let pt1 = await ga.receive(ctx1) +``` + +### Prototype WebIDL Definition + +```javascript + +// +// Type definitions +// + +// The MLSMessageType is a way to distinguished returned values. + +enum MLSObjectType { + "group-epoch", + "group-identifier", + "group-info", + "client-identifier", + "credential-basic", + "key-package", + "proposal", + "commit-output", + "commit-processed", + "welcome", + "exporter-output", + "exporter-label", + "exporter-context", + "application-message-ciphertext", + "application-message-plaintext", +}; + +dictionary MLSBytes { + required MLSObjectType type; + required Uint8Array content; +}; + +// The MLSGroupMember struct is a non-standard MLS object constructed as a way +// to return the link between a Client Identifier and a Credential. This is +// typically returned inside a list of members when calling the GroupMembers +// function. + +dictionary MLSGroupMember { + required Uint8Array clientId; + required Uint8Array credential; +}; + +// The MLSGroupDetails struct is a non-standard MLS object which reflects the +// Membership for a Group at a certain Epoch. The Application can always request +// the membership of the current Group and store that information for future +// purposes. + +dictionary MLSGroupDetails { + required MLSObjectType type; + required Uint8Array groupId; + required Uint8Array groupEpoch; + required sequence members; +}; + +// The MLSCommitOutput is a non-standard MLS object that is returned by the +// underneath library after performing an MLS Group Operation. It contains the +// commit (for existing members), the welcome (for eventual new members), the +// identifier of the client that performed the operation for convenience, and +// additional information for eventual use by advanced configuration. As of now, +// those advanced parameters will typically be empty. + +dictionary MLSCommitOutput { + required MLSObjectType type; + required Uint8Array groupId; + required Uint8Array commit; + Uint8Array welcome; + Uint8Array groupInfo; + Uint8Array ratchetTree; + Uint8Array clientId; +}; + +// The MLSExporterOutput is a non-standard MLS object that contains information +// that was used to generate an exporter value as well as the value of the exporter +// itself. + +dictionary MLSExporterOutput { + required MLSObjectType type; + required Uint8Array groupId; + required Uint8Array groupEpoch; + required Uint8Array label; + required Uint8Array context; + required Uint8Array secret; +}; + +// The MLSReceived is a non-standard MLS protocol object which contains the type +// of the message processed by the decryption function (MLS.receive). + +dictionary MLSReceived { + required MLSObjectType type; + required Uint8Array groupId; + Uint8Array groupEpoch; + Uint8Array content; + MLSCommitOutput commitOutput; +}; + +// Type aliases + +typedef MLSBytes MLSClientId; +typedef MLSBytes MLSGroupId; +typedef MLSBytes MLSCredential; +typedef MLSBytes MLSKeyPackage; +typedef MLSBytes MLSProposal; +typedef (MLSBytes or Uint8Array) MLSBytesOrUint8Array; +typedef (Uint8Array or UTF8String) Uint8ArrayOrUTF8String; +typedef (MLSBytes or Uint8Array or UTF8String) MLSBytesOrUint8ArrayOrUTF8String; + +// +// API +// + +// In all these exposed functions, the principal is derived by the DOM code to +// perform storage partitioning based on Origin+OriginSuffix. + +[Pref="security.mls.enabled", +SecureContext, +Exposed=(Window,Worker)] + +interface MLS { + +// The deleteStateForOrigin function will delete all databases for the current +// Origin (Host+OriginSuffix). + + [Throws] + Promise deleteState(); + +// The generateIdentity function will generate a signature keypair based on the +// default ciphersuite. What is returned is a Client Identifier (the hash of the +// public key) so that public keys are not exposed to the users. There is currently +// no API which returns the private signature key. + + [Throws] + Promise generateIdentity(); + +// The generateCredentialBasic function allows to generate a single "basic" MLS +// credential which are necessary for building KeyPackages. Other types of +// credentials can be generated externally. (eg. this is internally a Uint8Array +// which can internally be constructed from a string "alice") + +[Throws] + Promise generateCredential(Uint8ArrayOrString credentialContent); + +// The generateKeyPackage function is leveraging a Signature keypair represented +// by a client identifier handler, as well as an credential to generate and sign +// KeyPackages. These KeyPackages are public values that can be distributed to +// other users and used to add clients to groups. + + [Throws] + Promise generateKeyPackage(MLSBytesOrUint8Array clientId, MLSBytesOrUint8Array credential); + +// The groupCreate function will create a Group View for a specific group and +// client identifier based on the identity and credential. + + [Throws] + Promise groupCreate(MLSBytesOrUint8Array clientId, MLSBytesOrUint8Array credential); + +// The groupGet function is a constructor for an MLSGroupView object + + [Throws] + Promise groupGet(MLSBytesOrUint8Array groupId, MLSBytesOrUint8Array clientId); + +// The groupJoin function processes a Welcome message for a specific Client to +// Join a Group. + + [Throws] + Promise groupJoin(MLSBytesOrUint8Array clientId, MLSBytesOrUint8Array welcome); +}; + +[Pref="security.mls.enabled", + SecureContext, + Exposed=(Window,Worker)] +interface MLSGroupView { + // The group identifier is constant across views of the same group + [Throws] + readonly attribute Uint8Array groupId; + // The client identifier is what makes it a view of the group + [Throws] + readonly attribute Uint8Array clientId; + + // This function will delete the state of the database for the client + // which is represented by this view + [Throws] + Promise deleteState(); + + // Add a client to the group using a key package + [Throws] + Promise add(MLSBytesOrUint8Array keyPackage); + + // Propose to Add a client to the group + // (this generates a proposal which when received will generate the + // commit output) + [Throws] + Promise proposeAdd(MLSBytesOrUint8Array keyPackage); + + // Remove a client from the group + // (For security reason self removing MUST be proposed instead!) + [Throws] + Promise remove(MLSBytesOrUint8Array remClientId); + + // Propose to Remove a client (possibly self) from the group + [Throws] + Promise proposeRemove(MLSBytesOrUint8Array remClientId); + + // Removes all users from the group apart from the client in the view + // (This could be named removeAll but self, after the commit is + // received the caller will be alone in the group and can call + // delete().) + [Throws] + Promise close(); + + // Get information about the current state of the group including + // identifier, epoch and current membership + [Throws] + Promise details(); + + // Encrypt a message to the group in the current epoch + [Throws] + Promise send(MLSBytesOrUint8ArrayOrString message); + + // Receive a message for the the current group and client identifiers + [Throws] + Promise receive(MLSBytesOrUint8Array message); + + // When a commit is generated but lost and cannot be received, the + // state can still move to the new epoch instead of calling receive on + // the commit message because we keep the pending commit in the state + [Throws] + Promise applyPendingCommit(); + + // Derive a secret for an external Application + [Throws] + Promise exportSecret(MLSBytesOrUint8ArrayOrString label, MLSBytesOrUint8Array context, unsigned long long length); + +}; + +``` + +### A more advanced example… + +```javascript +// !!! +// < Insert the code for the basic example here... > +// !!! + +// Charlie creates identity keypair, credential and key package +let c = await mls.generateIdentity() +let cc = await mls.generateCredential("charlie") +let ckp = await mls.generateKeyPackage(c, cc) + +// Alice adds Charlie to the group +let co2 = await ga.add(ckp) + +// Alice and Bob process the commit which is adding Charlie +let agide2 = await ga.receive(co2.commit) +let bgide2 = await gb.receive(co2.commit) + +// Charlie joins the group and sends a message +let gc = await mls.groupJoin(c, co2.welcome) +let ctx2 = await gc.send("Hi all") + +// Alice and Bob receive charlie's message +let apt2 = await ga.receive(ctx2) +let bpt2 = await gb.receive(ctx2) + +// Charlie removes Bob from the group +let co3 = await gc.remove(b) + +// Each member receives the commit removing Bob +let agide3 = await ga.receive(co3.commit) +let bgide3 = await gb.receive(co3.commit) +let cgide3 = await gc.receive(co3.commit) + +// Alice proposes to be removed from the group +let p4 = await ga.proposeRemove(a) + +// Charlie processes the proposal and generates a commit output +let co4 = await gc.receive(p4) + +// Alice and Charlie process the commit to remove Alice +let agide4 = await ga.receive(co4.commitOutput.commit) +let cgide4 = await gc.receive(co4.commitOutput.commit) + +// Generate identities, credentials and key packages for +// delphine and ernest +let d = await mls.generateIdentity() +let e = await mls.generateIdentity() +let dc = await mls.generateCredential("delphine") +let ec = await mls.generateCredential("ernest") +let dkp = await mls.generateKeyPackage(d, dc) +let ekp = await mls.generateKeyPackage(e, ec) + +// Charlie adds Delphine to the Group and process the commit +let co5 = await gc.add(dkp) +let cgide5 = await gc.receive(co5.commit) + +// Delphine uses the welcome to join the group +let gd = await mls.groupJoin(d, co5.welcome) + +// Delphine proposes to add Ernest to the group +let p6 = await gd.proposeAdd(ekp) + +// Charlie generate a commit output for Delphine's proposa to add Ernest +let rec6 = await gc.receive(p6) + +// Charlie and Delphine process the commit to add Ernest +let cgide6 = await gc.receive(rec6.commitOutput.commit) +let dgide6 = await gd.receive(rec6.commitOutput.commit) + +// Ernest joins the group +let ge = await mls.groupJoin(e, rec6.commitOutput.welcome) + +// Create exporter labels and context ("context" in ASCII) +const context_bytes = new Uint8Array([99, 111, 110, 116, 101, 120, 116]); const exporter_len = 32; + +// Ernest generates an exporter secret +let exporterOutput = await ge.exportSecret( + "label", context_bytes, exporter_len); + +// This is the shared secret for the group at this epoch +let secret = exporterOutput.secret; + +// Display group information for all group views +console.log(await gc.details()) +console.log(await gd.details()) +console.log(await ge.details()) +``` + +### Notes and additional information + +**Exporting secrets for your application** + +While sending and receiving MLS application messages through the API is very +convenient, applications sometimes need to generate secrets for their own +use. These symmetric secrets can be generated via the export\_secret API +function using a specific label and context. Generating such secrets is safe and +does not expose anything about the internal secret state of the protocol as this +is done through a KDF. Note that the secret is specific to a specific epoch of +the group. + +**Partitioning and storage in the browser** + +As of now, the MLS state is stored encrypted at rest in the profile of the user, +similar to credentials so that it can later be migrated. The key for each +database is currently located in the same directory along the encrypted +database. The state is partitioned by Origin (origin+originAttributeSuffix) and +this was checked with multiple teams, including Privacy and Storage. + +**Notes on deleting MLS public and secret state** + +The MLS state for the origin (including secrets) can be deleted by the +application by calling the delete state function of the API from within this +origin. The user can also clean the state using the UI to “clear all site data” +(by clicking on the lock icon) or by calling the API via the console if they +don’t wish to clear their cookies at the same time. + +**Notes on security for large groups** + +It is often asked why anyone would think a thousand participant group could be +honest. The formal security guarantees are the same at a scale of two +participants and for large groups: the cryptographic properties are that \- when +\- the members of the group are honest then during that period of time you +benefit from great Forward Secrecy and Post-Compromise-Security properties. + +### Ongoing work + +- Alignment with other platforms such as Android +- Web Application Integrity, Consistency and Transparency effort +- Interaction with WebRTC \+ SFrame / MLS +- Get feedback to be in a good shape before submitting to standardization + +### Next steps + +- We will have to decide about an improved UX and UI for the long state storage, + and the permissions to add and clear state. +- We expect to provide **custom proposals** and **external join** features. +- We also will likely extend the API to take lists of users to Add and Remove to + reduce the number of messages to send to other participants. +- We anticipate that there will be a need for the application and users to + annotate identifiers from other users in a way that cannot be modified by + applications (e.g. to record that a user identity has been authenticated out + of bound). +- Consider and discuss the idea of migrating the management of MLS cryptographic + keys to the Credential Manager. + +### Conclusion + +The experimental Web API for Messaging Layer Security aims to provide a robust, +privacy-preserving solution for secure group communication on the web and the +internet. As this is not a web-standard, the feature has to be enabled in +about:config. + +In parallel of this effort, Mozilla is partnering with major actors of the +industry to bring more guarantees to users when running security and privacy +critical sites through Web Application integrity, consistency and transparency +mechanisms which will help + +By leveraging MLS and aligning with open standards, Mozilla seeks to enhance +user security and foster innovation within the web platform community. From edce6909559b123999489b768d14debe9f9149d7 Mon Sep 17 00:00:00 2001 From: Benjamin Beurdouche Date: Wed, 12 Feb 2025 11:22:32 +0100 Subject: [PATCH 02/24] Initial explainer for WAICT --- waict-explainer.md | 102 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 waict-explainer.md diff --git a/waict-explainer.md b/waict-explainer.md new file mode 100644 index 0000000..303539a --- /dev/null +++ b/waict-explainer.md @@ -0,0 +1,102 @@ +# WAICT (Web Application Integrity, Consistency, and Transparency) + +## 1. What Are We Doing? +We aim to **raise the security and privacy bar for web applications** by ensuring three key properties: + +1. **Integrity**: Prevent any unauthorized modification of site code—even if served by a third-party CDN. +2. **Consistency**: Give users confidence that they receive the *same* code everyone else does (i.e., no user-specific malicious versions). +3. **Transparency**: Ensures stronger security for the Consistency mechanism. Encourage append-only logs that record published code versions, deterring hidden or short-lived changes and helping external audits. + +Our goal is a **standardized, browser-based mechanism** that sites can easily opt into—without forcing users to install extensions. While we propose high-level strategy and a technical proposal here, **technical details remain open for discussion** among browser vendors, web application providers, and standards bodies. + +--- + +## 2. Why Are We Doing This? +### Security-Critical Applications +Webmail, secure messaging, banking, and other sensitive sites face *strong* threats: +- **Insider Threats**: Malicious insiders, internal bugs, or selective content modifications. +- **Hosting Compromises**: Attackers or misconfigurations can serve altered code. + +### User Trust +Users **expect** they receive authentic code, consistent across all users, but the ecosystem does not have this property. This is particularly vital for end-to-end encryption: the page’s integrity is part of the security chain. + +### Extensions & Explicit Consent +Currently, only specialized browser extensions (like CodeVerify) can provide stronger assurances. But extensions require extra user steps, limiting adoption. Our approach makes these protections native and more widely available. + +--- + +## 3. How Are We Doing This? +1. **Leverage & Extend SRI** + - Instead of a per-resource hash, we propose a **manifest-based** approach listing all subresources (script, style, etc.) with, typically, a single signature covering the manifest to remove performance problems. + +2. **HTTP Header (possibly an extension of CSP)** + - Introduce an “integrity-manifest” directive to specify: + - **Where** the browser fetches the manifest (`integrity-manifest-src`). + - **How** strictly to enforce integrity (`integrity-enforcement-level`). + - If necessary raise UI or block the page based on the enforcement level. + +3. **Add Transparency & Consistency** + - **Signed Manifests & Logs**: Sites can embed cryptographic proof of logging each manifest into an append-only record. + - **Proof of Inclusion**: Browsers verify that they trust the proof of inclusion but do not need to look into the content. The auditability prevents stealth “one-off” versions. + - **Downgrade Prevention**: Once a domain is known to enforce these policies, it can request browsers to not accept weaker modes for a specific amount of time (not exactly like, but similar to HSTS). + +4. **Prototype & Standardize** + - We’ll refine prototypes through collaboration with major actors (e.g., WebAppSec at W3C) and consider parallel IETF work for the logging/transparency pieces. + - **Implementation details** though we want to align on the high level information to raise to the user (if any), this should likely remain implementation specific on the browser side. + +--- + +## 4. Why Integrity and Transparency Together? +- **Short Attack Windows**: Without transparency, a malicious version can appear briefly and vanish with minimal trace. It could achieve local consistency even if checked through multiple network paths. +- **Stronger Deterrence**: A public log, plus manifest-based integrity, makes *every* release visible. Hiding malicious changes becomes much riskier. +- **Efficient Cohesion**: Designing them simultaneously avoids redundant or conflicting mechanisms and simplifies adoption for large, dynamic sites. + +--- + +## 5. Why We Think We Can Actually Do This +- **Real Precedent: CodeVerify** + - Meta built an extension verifying scripts for WhatsApp, Instagram, and Messenger. It works in production, proving feasibility—though it remains optional and partial. +- **Scalability for Large Sites** + - Our manifest approach is explicitly designed for high-traffic, multi-CDN services and A/B testing. +- **Browser & Site Interest** + - Multiple vendors have indicated willingness to explore and prototype stronger security. +- **Incremental Adoption** + - Non-participating sites are unaffected. Early adopters can start with basic script integrity and then expand to styles, WASM, or further subresources. They can also choose to deploy different enforcement levels and/or enable the downgrade protection gradually. + +--- + +## 6. Why Aren’t SRI or CodeVerify Sufficient on Their Own? +1. **Subresource Integrity (SRI)** + - **Limitations**: Requires distinct hashes for every resource; large sites find this unwieldy. It also *does not* provide transparency or consistency assurances. It is restricted to scripts at this time. Similarily, import-map-integrity only covers ES modules and not packages and Sig-based SRI is too costly for large sets of resources and doesn't cover Consistency... +2. **CodeVerify Extension** + - **Limitations**: Relies on user installation, cannot verify all resource types, and remains out-of-band from standard browser features. + +By integrating such ideas *natively*—with a manifest-based approach plus transparency logs—we bring default security to all users without requiring an extension. + +--- + +## 7. Who Needs It, and Who Will Deploy It? +- **Needs It** + - **High-Security Apps**: Secure messaging, financial portals, healthcare sites. + - **Smaller Sites**: Quickly benefit from the same protections with minimal overhead. +- **Willing to Implement** + - **Browser Vendors**: Indicated interest in providing a standard solution to solve the strategic security objective. Firefox is invested in the topic and would ideally prefer to implement a standard. + - **Large Content Providers**: Entities serving traffic eg. Cloudflare or Critical sites like Meta’s Facebook, WhatsApp, Instagram sites. + +--- + +## 8. Conclusion and Next Steps +We propose a **two-phase** approach: +1. **Integrity**: Extend SRI with a manifest-based signature approach and a header to announce the integrity configuration. +2. **Consistency & Transparency**: Integrate cryptographic proofs and public logging to deter targeted attacks and enable long-term audits. + +Our next steps include **prototyping** these mechanisms, collaborating across browsers and large-scale websites, and preparing a draft for standardization in W3C WebAppSec and possibly IETF. We want to **align on the high-level strategic idea** that browsers can natively enforce integrity, consistency, and transparency—while acknowledging that **the specifics of this proposal remain open to technical debate**. + +By designing integrity and transparency together, we can make the web more trustworthy, ensuring that all users can rely on security-critical sites to deliver the code they promise, consistently and visibly. + +--- + +## 9. More details + +You can find more details in [this document](https://docs.google.com/document/d/16-cvBkWYrKlZHXkWRFvKGEifdcMthUfv-LxIbg6bx2o). + From 079c0a8553ad7d2e3be9eb51a3fb74f6b09178c6 Mon Sep 17 00:00:00 2001 From: Benjamin Beurdouche Date: Tue, 18 Feb 2025 16:31:45 +0100 Subject: [PATCH 03/24] Notes from Richard --- waict-explainer.md | 65 +++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/waict-explainer.md b/waict-explainer.md index 303539a..f14c616 100644 --- a/waict-explainer.md +++ b/waict-explainer.md @@ -3,8 +3,8 @@ ## 1. What Are We Doing? We aim to **raise the security and privacy bar for web applications** by ensuring three key properties: -1. **Integrity**: Prevent any unauthorized modification of site code—even if served by a third-party CDN. -2. **Consistency**: Give users confidence that they receive the *same* code everyone else does (i.e., no user-specific malicious versions). +1. **Integrity**: Prevent any unauthorized modification of site code—even if served by a third-party CDN. +2. **Consistency**: Give users confidence that they receive the *same* code everyone else does (i.e., no user-specific malicious versions). 3. **Transparency**: Ensures stronger security for the Consistency mechanism. Encourage append-only logs that record published code versions, deterring hidden or short-lived changes and helping external audits. Our goal is a **standardized, browser-based mechanism** that sites can easily opt into—without forcing users to install extensions. While we propose high-level strategy and a technical proposal here, **technical details remain open for discussion** among browser vendors, web application providers, and standards bodies. @@ -14,11 +14,11 @@ Our goal is a **standardized, browser-based mechanism** that sites can easily op ## 2. Why Are We Doing This? ### Security-Critical Applications Webmail, secure messaging, banking, and other sensitive sites face *strong* threats: -- **Insider Threats**: Malicious insiders, internal bugs, or selective content modifications. -- **Hosting Compromises**: Attackers or misconfigurations can serve altered code. +- **Insider Threats**: Malicious insiders, internal bugs, or selective content modifications. +- **Hosting Compromises**: Attackers or misconfigurations can serve altered code. ### User Trust -Users **expect** they receive authentic code, consistent across all users, but the ecosystem does not have this property. This is particularly vital for end-to-end encryption: the page’s integrity is part of the security chain. +This is particularly vital for end-to-end encryption: the page’s integrity is the most important part of the security chain. (because it's encrypted everywhere else, the endpoints are the weak link, so ensuring security is strong there is paramount) ### Extensions & Explicit Consent Currently, only specialized browser extensions (like CodeVerify) can provide stronger assurances. But extensions require extra user steps, limiting adoption. Our approach makes these protections native and more widely available. @@ -26,68 +26,68 @@ Currently, only specialized browser extensions (like CodeVerify) can provide str --- ## 3. How Are We Doing This? -1. **Leverage & Extend SRI** +1. **Leverage & Extend SRI** - Instead of a per-resource hash, we propose a **manifest-based** approach listing all subresources (script, style, etc.) with, typically, a single signature covering the manifest to remove performance problems. -2. **HTTP Header (possibly an extension of CSP)** - - Introduce an “integrity-manifest” directive to specify: - - **Where** the browser fetches the manifest (`integrity-manifest-src`). - - **How** strictly to enforce integrity (`integrity-enforcement-level`). +2. **HTTP Header (possibly an extension of CSP)** + - Introduce an “integrity-manifest” directive to specify: + - **Where** the browser fetches the manifest (`integrity-manifest-src`). + - **How** strictly to enforce integrity (`integrity-enforcement-level`). - If necessary raise UI or block the page based on the enforcement level. -3. **Add Transparency & Consistency** - - **Signed Manifests & Logs**: Sites can embed cryptographic proof of logging each manifest into an append-only record. +3. **Add Transparency & Consistency** + - **Signed Manifests & Logs**: Sites can embed cryptographic proof of logging each manifest into an append-only record. - **Proof of Inclusion**: Browsers verify that they trust the proof of inclusion but do not need to look into the content. The auditability prevents stealth “one-off” versions. - **Downgrade Prevention**: Once a domain is known to enforce these policies, it can request browsers to not accept weaker modes for a specific amount of time (not exactly like, but similar to HSTS). -4. **Prototype & Standardize** - - We’ll refine prototypes through collaboration with major actors (e.g., WebAppSec at W3C) and consider parallel IETF work for the logging/transparency pieces. +4. **Prototype & Standardize** + - We’ll refine prototypes through collaboration with major actors (e.g., WebAppSec at W3C) and consider parallel IETF work for the logging/transparency pieces. - **Implementation details** though we want to align on the high level information to raise to the user (if any), this should likely remain implementation specific on the browser side. --- ## 4. Why Integrity and Transparency Together? - **Short Attack Windows**: Without transparency, a malicious version can appear briefly and vanish with minimal trace. It could achieve local consistency even if checked through multiple network paths. -- **Stronger Deterrence**: A public log, plus manifest-based integrity, makes *every* release visible. Hiding malicious changes becomes much riskier. +- **Stronger Deterrence**: A public log, plus manifest-based integrity, makes *every* release visible. Hiding malicious changes becomes much riskier. - **Efficient Cohesion**: Designing them simultaneously avoids redundant or conflicting mechanisms and simplifies adoption for large, dynamic sites. --- ## 5. Why We Think We Can Actually Do This -- **Real Precedent: CodeVerify** - - Meta built an extension verifying scripts for WhatsApp, Instagram, and Messenger. It works in production, proving feasibility—though it remains optional and partial. -- **Scalability for Large Sites** - - Our manifest approach is explicitly designed for high-traffic, multi-CDN services and A/B testing. -- **Browser & Site Interest** - - Multiple vendors have indicated willingness to explore and prototype stronger security. -- **Incremental Adoption** +- **Real Precedent: CodeVerify** + - Meta built an extension verifying scripts for WhatsApp, Instagram, and Messenger. It works in production, used by actual users, proving feasibility-though it remains optional and partial. +- **Scalability for Large Sites** + - Our manifest approach is explicitly designed for high-traffic, multi-CDN services and A/B testing. +- **Browser & Site Interest** + - Multiple vendors have indicated willingness to explore and prototype stronger security. +- **Incremental Adoption** - Non-participating sites are unaffected. Early adopters can start with basic script integrity and then expand to styles, WASM, or further subresources. They can also choose to deploy different enforcement levels and/or enable the downgrade protection gradually. --- ## 6. Why Aren’t SRI or CodeVerify Sufficient on Their Own? -1. **Subresource Integrity (SRI)** - - **Limitations**: Requires distinct hashes for every resource; large sites find this unwieldy. It also *does not* provide transparency or consistency assurances. It is restricted to scripts at this time. Similarily, import-map-integrity only covers ES modules and not packages and Sig-based SRI is too costly for large sets of resources and doesn't cover Consistency... -2. **CodeVerify Extension** - - **Limitations**: Relies on user installation, cannot verify all resource types, and remains out-of-band from standard browser features. +1. **Subresource Integrity (SRI)** + - **Limitations**: Requires distinct hashes colocated for every resource; large sites find this unwieldy. It also *does not* provide transparency or consistency assurances. It is restricted to scripts at this time. SRI also provides no inclusion or exclusion benefits on the set of scripts. This might be included in transparency, as it governs the addition or removal of scripts for individual users or page loads. Similarily, import-map-integrity only covers ES modules and not packages and Sig-based SRI is too costly for large sets of resources and doesn't cover Consistency... +2. **CodeVerify Extension** + - **Limitations**: Relies on user installation, cannot verify all resource types, and remains out-of-band from standard browser features. Browser Extension APIs are insufficent for strong protections. -By integrating such ideas *natively*—with a manifest-based approach plus transparency logs—we bring default security to all users without requiring an extension. +By integrating such ideas *natively*—with a manifest-based approach plus transparency logs—we bring increased default security to all users without requiring an extension. --- ## 7. Who Needs It, and Who Will Deploy It? -- **Needs It** - - **High-Security Apps**: Secure messaging, financial portals, healthcare sites. +- **Needs It** + - **High-Security Apps**: Secure messaging, financial portals, healthcare sites. - **Smaller Sites**: Quickly benefit from the same protections with minimal overhead. -- **Willing to Implement** +- **Willing to Implement** - **Browser Vendors**: Indicated interest in providing a standard solution to solve the strategic security objective. Firefox is invested in the topic and would ideally prefer to implement a standard. - **Large Content Providers**: Entities serving traffic eg. Cloudflare or Critical sites like Meta’s Facebook, WhatsApp, Instagram sites. --- ## 8. Conclusion and Next Steps -We propose a **two-phase** approach: -1. **Integrity**: Extend SRI with a manifest-based signature approach and a header to announce the integrity configuration. +We propose a **two-phase** approach: +1. **Integrity**: Extend SRI with a manifest-based signature approach and a header to announce the integrity configuration. 2. **Consistency & Transparency**: Integrate cryptographic proofs and public logging to deter targeted attacks and enable long-term audits. Our next steps include **prototyping** these mechanisms, collaborating across browsers and large-scale websites, and preparing a draft for standardization in W3C WebAppSec and possibly IETF. We want to **align on the high-level strategic idea** that browsers can natively enforce integrity, consistency, and transparency—while acknowledging that **the specifics of this proposal remain open to technical debate**. @@ -99,4 +99,3 @@ By designing integrity and transparency together, we can make the web more trust ## 9. More details You can find more details in [this document](https://docs.google.com/document/d/16-cvBkWYrKlZHXkWRFvKGEifdcMthUfv-LxIbg6bx2o). - From 73c21491a138a813a586c1941e7ae05af9c7efcc Mon Sep 17 00:00:00 2001 From: Benjamin Beurdouche Date: Thu, 20 Feb 2025 20:36:05 +0100 Subject: [PATCH 04/24] Update the preference for MLS --- MessagingLayerSecurity.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 8577896..40f8275 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -1,7 +1,7 @@ # Explainer: Prototype Web API for Messaging Layer Security (MLS) -[Benjamin Beurdouche](mailto:bbeurdouche@mozilla.com) -Last updated: November 29, 2024 +[Benjamin Beurdouche](mailto:beurdouche@mozilla.com) +Last updated: February 20, 2025 ### Overview @@ -87,9 +87,13 @@ application level by defining coherent MLS group and client configurations, the MLS layer messages will be interoperable and applications will be able to build a shared group. -### How do I enable the experiment ? +### How do I enable the experiment ? -**Navigate to \`about:config\` and set \`security.mls.enabled\` to \`true\`.** +If you are not already part of an Origin Trial, navigate to **\`about:config\`**. + +For Firefox 135: set **\`security.mls.enabled\`** to **\`true\`**. + +For Firefox 136+: set **\`dom.origin-trials.mls.state\`** to **\`1\`**. ### Terminology @@ -169,6 +173,9 @@ let ga = await mls.groupJoin(a, co1.welcome) let pt1 = await ga.receive(ctx1) ``` +Note that, to ease testing, the code above runs both participants +but each browser will typically run one participant. + ### Prototype WebIDL Definition ```javascript From 02f60c20a27debb7113b2753ab6493762f18b9a0 Mon Sep 17 00:00:00 2001 From: Benjamin Beurdouche Date: Wed, 23 Apr 2025 15:33:23 +0200 Subject: [PATCH 05/24] Fix presentation issue --- MessagingLayerSecurity.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 40f8275..f224db2 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -42,11 +42,11 @@ to hundreds of thousands of participants. The MLS API provides applications with two main capabilities: * Group management: applications can manage the participation of different -* entities, including the current browser, in groups. + entities, including the current browser, in groups. * Secure messaging: once -* created, a group generates a shared secret that can be used to provide -* end-to-end protected messaging with group participants. + created, a group generates a shared secret that can be used to provide + end-to-end protected messaging with group participants. This explainer outlines the goals, design, and potential use cases of the API. From 1bd1987dcfabb16d1f9043fcda488ee76ad81378 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Wed, 10 Sep 2025 11:17:13 +0200 Subject: [PATCH 06/24] Added Users problems --- MessagingLayerSecurity.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index f224db2..a78d6f5 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -1,7 +1,16 @@ -# Explainer: Prototype Web API for Messaging Layer Security (MLS) +# Explainer: Web API for Messaging Layer Security (MLS) + +[Benjamin Beurdouche](mailto:beurdouche@mozilla.com), [Anna Weine](https://github.com/Frosne) +Last updated: September 10, 2025 + +### User problems to be solved + + +The Messaging Layer Security (MLS) standard ([RFC 9420](https://www.rfc-editor.org/rfc/rfc9420.html)) addresses the challenges of scalable, efficient, and standardized end-to-end encryption for group messaging, while ensuring critical security properties such as forward secrecy (FS), post-compromise security (PCS) for groups with more than two participants. + +The standard has already attracted significant attention, with several major vendors expressing interest in implementing it within their products. Providing a single, standardized, and interoperable approach would offer substantial benefits to messaging application developers as well as the organisations willing to deploy MLS-based communication facilities, enabling them to deliver native, secure messaging support on the web efficiently and reliably. Once supported across all major browsers, developers would be able to write the integration code once and have it work consistently across platforms, significantly reducing development complexity and improving reliability. -[Benjamin Beurdouche](mailto:beurdouche@mozilla.com) -Last updated: February 20, 2025 ### Overview From 7aac46e0316d82ebd06e5ca30f557daca03ec62c Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Wed, 10 Sep 2025 11:18:58 +0200 Subject: [PATCH 07/24] Style improvements --- MessagingLayerSecurity.md | 1 + 1 file changed, 1 insertion(+) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index a78d6f5..826193b 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -1,6 +1,7 @@ # Explainer: Web API for Messaging Layer Security (MLS) [Benjamin Beurdouche](mailto:beurdouche@mozilla.com), [Anna Weine](https://github.com/Frosne) + Last updated: September 10, 2025 ### User problems to be solved From b66d0140518e7fcd16f01c4766c974c452452387 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Wed, 17 Sep 2025 17:31:23 +0200 Subject: [PATCH 08/24] + Methodology --- MessagingLayerSecurity.md | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 826193b..3d3b0c7 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -13,11 +13,26 @@ The Messaging Layer Security (MLS) standard ([RFC 9420](https://www.rfc-editor.o The standard has already attracted significant attention, with several major vendors expressing interest in implementing it within their products. Providing a single, standardized, and interoperable approach would offer substantial benefits to messaging application developers as well as the organisations willing to deploy MLS-based communication facilities, enabling them to deliver native, secure messaging support on the web efficiently and reliably. Once supported across all major browsers, developers would be able to write the integration code once and have it work consistently across platforms, significantly reducing development complexity and improving reliability. -### Overview +### Methodology for approaching & evaluating solutions + +All vendors require different functionalities to achieve their objectives. Prior to evaluating potential approaches, it is necessary to collect functional requirements from prospective implementers. This process enables a clear distinction between core and optional functionalities. + +Then, the proposed methodology for assessing potential solutions is based on the following criteria: + +1) Completeness: Priority is given to solutions that provide comprehensive coverage of core functionalities, while optionally supporting additional functions. + +2) Simplicity: The ease of implementation and adoption of the solution. + +3) Interoperability: The ability of the solution to function seamlessly with other potential implementations. + + +### Prior/Existing features and/or proposals (if any) that attempt to solve the problem(s) + +### Flaws or limitations in existing features/proposals that prevent solving the problem(s) + +### Motivation for this explainer, why we think we can do better than the status quo or other proposals + -This document describes a Web API for the Messaging Layer Security (MLS) -protocol (RFC 9420). MLS provides group key exchange for changing groups, which -enables secure communication within those groups. ### Problem statement @@ -43,7 +58,7 @@ This enables applications for **secure group communication** including video-conferencing (SFrameTransform for WebRTC, Media Over QUIC,...), secure messaging (RCS, MIMI), encrypted cloud storage, and more. -### Proposal +### Outline of a proposed solution Messaging Layer Security (MLS) (RFC 9420) provides convenient and secure ***Continuous Group Key Agreement (CGKA) for dynamic groups***, ranging from one From 3a85fcc6d1dc460264c0c60fa38572a1403aef79 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Wed, 17 Sep 2025 17:32:52 +0200 Subject: [PATCH 09/24] Added some questions to methodology --- MessagingLayerSecurity.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 3d3b0c7..01967ad 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -17,11 +17,11 @@ The standard has already attracted significant attention, with several major 3) Interoperability: The ability of the solution to function seamlessly with other potential implementations. From f1ca991139fdc8c5b3f26b697999b51007d661e4 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Tue, 23 Sep 2025 15:50:10 +0200 Subject: [PATCH 10/24] Added Prior proposals and their flaws --- MessagingLayerSecurity.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 01967ad..84b9554 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -19,17 +19,33 @@ All vendors require different functionalities to achieve their objectives. Prior Then, the proposed methodology for assessing potential solutions would be based on the following criteria: -1) Completeness: Priority is given to solutions that provide comprehensive coverage of core functionalities, while optionally supporting additional functions. +1) Completeness (Modularity??): Priority is given to solutions that provide comprehensive coverage of core functionalities, while optionally supporting additional functions. 2) Simplicity: The ease of implementation and adoption of the solution. 3) Interoperability: The ability of the solution to function seamlessly with other potential implementations. +4) Security. MLS uses advanced cryptographical techniques, which are not trivial to implement correctly. A robust API should provide an clear abstraction over these features that will allow a secure implementation. + ### Prior/Existing features and/or proposals (if any) that attempt to solve the problem(s) +Several existing initiatives aim to address the stated user problem. + + + +1) The Messaging Layer Security (MLS) Architecture document published as [RFC 9750](https://datatracker.ietf.org/doc/rfc9750) defines the architectural framework for employing MLS within a general secure group messaging infrastructure. + +2) Wire has recently advertised the [support and adoption](https://wire.com/hubfs/Whitepapers/Wire%20MLS%20White%20Paper.pdf) of MLS. + +3) Amazon Web Services (AWS) Labs has released an [implementation](https://github.com/awslabs/mls-rs) of the MLS protocol. + +4) Messaging Layer Security over ActivityPub [draft report](https://swicg.github.io/activitypub-e2ee/mls) describes the interfaces between MLS and ActivityPub. + ### Flaws or limitations in existing features/proposals that prevent solving the problem(s) +None of the aforementioned features directly address the challenge of establishing a single, unified standard. + ### Motivation for this explainer, why we think we can do better than the status quo or other proposals From e744385ca5847e1e9366bc84b8e4ac73f9356d0c Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Tue, 23 Sep 2025 16:15:19 +0200 Subject: [PATCH 11/24] Added Motivation --- MessagingLayerSecurity.md | 88 ++------------------------------------- 1 file changed, 4 insertions(+), 84 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 84b9554..a5f7a30 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -2,7 +2,7 @@ [Benjamin Beurdouche](mailto:beurdouche@mozilla.com), [Anna Weine](https://github.com/Frosne) -Last updated: September 10, 2025 +Last updated: September 23, 2025 ### User problems to be solved , and less error-prone interface. ### Outline of a proposed solution -Messaging Layer Security (MLS) (RFC 9420) provides convenient and secure -***Continuous Group Key Agreement (CGKA) for dynamic groups***, ranging from one -to hundreds of thousands of participants. - -The MLS API provides applications with two main capabilities: - -* Group management: applications can manage the participation of different - entities, including the current browser, in groups. - -* Secure messaging: once - created, a group generates a shared secret that can be used to provide - end-to-end protected messaging with group participants. - - This explainer outlines the goals, design, and potential use cases of the API. - -### Goals - -1. **Provide a Continuous Group Key Agreement**: We want to enable Web and -Internet applications to use MLS as a way to build and manage groups using its -secure group key establishment directly from the browser, in particular for -End-to-End Encrypted applications. - -2. **State-of-the-Art Security**: Manipulate sensitive values and cryptographic -secrets of the protocol natively instead of exposing them to the web -application. Shipping an up-to-date MLS library which removes the need for -application developers to have a dedicated evaluation and software lifecycle for -this critical component. Similar to TLS, QUIC or WebRTC, ensure to provide a -high quality implementation to users. - -3. **Privacy and avoid user tracking**: Prevent user tracking by using -traditional techniques of partitioning the MLS state by origin. This will ensure -that strong identifiers like public keys are not reused across sites. - -4. **Ensure Performance**: Avoid back and forth between JavaScript, C++, storage -and cryptographic computations. Handle everything natively within browser native -code. - -### Non-Goals - -1. **Expose all possible MLS functionality**: The MLS protocol does not -currently have a “standard” API as it can be used in many different ways. We -will provide a significant subset of all these possibilities starting with safe -defaults and will listen for feedback in case extensions are requested by -developers. - -2. **Guarantee full interoperability across applications**: We cannot force that -different applications are interoperable, especially in a federated -context. However if service providers decide to agree on interoperability at the -application level by defining coherent MLS group and client configurations, the -MLS layer messages will be interoperable and applications will be able to build -a shared group. - -### How do I enable the experiment ? - -If you are not already part of an Origin Trial, navigate to **\`about:config\`**. - -For Firefox 135: set **\`security.mls.enabled\`** to **\`true\`**. +Our goal is to provide a simplified MLS API for Web applications. -For Firefox 136+: set **\`dom.origin-trials.mls.state\`** to **\`1\`**. +This includes basic functions for group management, such as adding and removing members. For groups, both secure messaging using the internal MLS key schedule and exporting of keying material for more advanced applications is possible. ### Terminology From 05dc7f11bd9d9ea0cf62591a71b6a17feb39c321 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Tue, 23 Sep 2025 17:58:36 +0200 Subject: [PATCH 12/24] Proposed solution update --- MessagingLayerSecurity.md | 291 +++++--------------------------------- 1 file changed, 37 insertions(+), 254 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index a5f7a30..946750f 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -56,19 +56,46 @@ Our goal is to provide a simplified MLS API for Web applications. This includes basic functions for group management, such as adding and removing members. For groups, both secure messaging using the internal MLS key schedule and exporting of keying material for more advanced applications is possible. -### Terminology +The key notion of any messaging protocol is a client. Client is an agent that uses this protocol to establish shared cryptographic state with other clients. The client does not have to be a part of a group yet. -A few key concepts of the MLS protocol that are necessary to understand the API. +Each client could be seen as a public indentity ("Alice", for example), a public encryption key, and a public signature key. Client credentials is a way to prove that a current member owns a specific identity (by proving the owning of the public key). The client identifier and public key -- along with any external credentials -- are often bundled into what is called a key package that is used to add clients to groups. -**Identities and Credentials** -The client is a participant in the protocol which is owned by users. Each -client, whether it is part of a group or not, has a unique identity or client -identifier which is a handle to a signature keypair. Each client can be -associated with a credential which is a way to reflect additional information -related to the identity. The default API offers a facility to create -credentials containing arbitrary strings called basic credentials but X509 or a -verifiable credential can be generated externally and be used in the API. +```javascript +let mls = new MLS() + +// Create identity for alice +let alice = await mls.generateIdentity() + +// Create credential for alice +let alice_credential = await mls.generateCredential(alice) + +// Bind the credential and indentity to one key package for alice +let alice_key_package = await mls.generateKeyPackage(alice, ac) + +TODO: Include some code examples of client setup here. Highlight the important attributes on the client objects. +``` + +Groups are collection of users. Each client included in a group is a member of the group. Each group member has access to the group's secrets. + +```javascript +// A user could create a group +let alice_group = await mls.groupCreate(alice, alice_credential); + +// Access the group information such as group members: +let alice_group_details = await alice_group.details().members; + +// Invite others to the group: +// We will talk about commits and context (ctx) later in the explainer +let commit_added_bob = await alice_group.add(bob_key_package); + +// Send a message to the group +let ctx = await alice_group.send(message); + +// Remove a member from a group +let commit_removed_bob = await alice_group.remove(bob); + +``` **Key Package** @@ -137,243 +164,6 @@ let pt1 = await ga.receive(ctx1) Note that, to ease testing, the code above runs both participants but each browser will typically run one participant. -### Prototype WebIDL Definition - -```javascript - -// -// Type definitions -// - -// The MLSMessageType is a way to distinguished returned values. - -enum MLSObjectType { - "group-epoch", - "group-identifier", - "group-info", - "client-identifier", - "credential-basic", - "key-package", - "proposal", - "commit-output", - "commit-processed", - "welcome", - "exporter-output", - "exporter-label", - "exporter-context", - "application-message-ciphertext", - "application-message-plaintext", -}; - -dictionary MLSBytes { - required MLSObjectType type; - required Uint8Array content; -}; - -// The MLSGroupMember struct is a non-standard MLS object constructed as a way -// to return the link between a Client Identifier and a Credential. This is -// typically returned inside a list of members when calling the GroupMembers -// function. - -dictionary MLSGroupMember { - required Uint8Array clientId; - required Uint8Array credential; -}; - -// The MLSGroupDetails struct is a non-standard MLS object which reflects the -// Membership for a Group at a certain Epoch. The Application can always request -// the membership of the current Group and store that information for future -// purposes. - -dictionary MLSGroupDetails { - required MLSObjectType type; - required Uint8Array groupId; - required Uint8Array groupEpoch; - required sequence members; -}; - -// The MLSCommitOutput is a non-standard MLS object that is returned by the -// underneath library after performing an MLS Group Operation. It contains the -// commit (for existing members), the welcome (for eventual new members), the -// identifier of the client that performed the operation for convenience, and -// additional information for eventual use by advanced configuration. As of now, -// those advanced parameters will typically be empty. - -dictionary MLSCommitOutput { - required MLSObjectType type; - required Uint8Array groupId; - required Uint8Array commit; - Uint8Array welcome; - Uint8Array groupInfo; - Uint8Array ratchetTree; - Uint8Array clientId; -}; - -// The MLSExporterOutput is a non-standard MLS object that contains information -// that was used to generate an exporter value as well as the value of the exporter -// itself. - -dictionary MLSExporterOutput { - required MLSObjectType type; - required Uint8Array groupId; - required Uint8Array groupEpoch; - required Uint8Array label; - required Uint8Array context; - required Uint8Array secret; -}; - -// The MLSReceived is a non-standard MLS protocol object which contains the type -// of the message processed by the decryption function (MLS.receive). - -dictionary MLSReceived { - required MLSObjectType type; - required Uint8Array groupId; - Uint8Array groupEpoch; - Uint8Array content; - MLSCommitOutput commitOutput; -}; - -// Type aliases - -typedef MLSBytes MLSClientId; -typedef MLSBytes MLSGroupId; -typedef MLSBytes MLSCredential; -typedef MLSBytes MLSKeyPackage; -typedef MLSBytes MLSProposal; -typedef (MLSBytes or Uint8Array) MLSBytesOrUint8Array; -typedef (Uint8Array or UTF8String) Uint8ArrayOrUTF8String; -typedef (MLSBytes or Uint8Array or UTF8String) MLSBytesOrUint8ArrayOrUTF8String; - -// -// API -// - -// In all these exposed functions, the principal is derived by the DOM code to -// perform storage partitioning based on Origin+OriginSuffix. - -[Pref="security.mls.enabled", -SecureContext, -Exposed=(Window,Worker)] - -interface MLS { - -// The deleteStateForOrigin function will delete all databases for the current -// Origin (Host+OriginSuffix). - - [Throws] - Promise deleteState(); - -// The generateIdentity function will generate a signature keypair based on the -// default ciphersuite. What is returned is a Client Identifier (the hash of the -// public key) so that public keys are not exposed to the users. There is currently -// no API which returns the private signature key. - - [Throws] - Promise generateIdentity(); - -// The generateCredentialBasic function allows to generate a single "basic" MLS -// credential which are necessary for building KeyPackages. Other types of -// credentials can be generated externally. (eg. this is internally a Uint8Array -// which can internally be constructed from a string "alice") - -[Throws] - Promise generateCredential(Uint8ArrayOrString credentialContent); - -// The generateKeyPackage function is leveraging a Signature keypair represented -// by a client identifier handler, as well as an credential to generate and sign -// KeyPackages. These KeyPackages are public values that can be distributed to -// other users and used to add clients to groups. - - [Throws] - Promise generateKeyPackage(MLSBytesOrUint8Array clientId, MLSBytesOrUint8Array credential); - -// The groupCreate function will create a Group View for a specific group and -// client identifier based on the identity and credential. - - [Throws] - Promise groupCreate(MLSBytesOrUint8Array clientId, MLSBytesOrUint8Array credential); - -// The groupGet function is a constructor for an MLSGroupView object - - [Throws] - Promise groupGet(MLSBytesOrUint8Array groupId, MLSBytesOrUint8Array clientId); - -// The groupJoin function processes a Welcome message for a specific Client to -// Join a Group. - - [Throws] - Promise groupJoin(MLSBytesOrUint8Array clientId, MLSBytesOrUint8Array welcome); -}; - -[Pref="security.mls.enabled", - SecureContext, - Exposed=(Window,Worker)] -interface MLSGroupView { - // The group identifier is constant across views of the same group - [Throws] - readonly attribute Uint8Array groupId; - // The client identifier is what makes it a view of the group - [Throws] - readonly attribute Uint8Array clientId; - - // This function will delete the state of the database for the client - // which is represented by this view - [Throws] - Promise deleteState(); - - // Add a client to the group using a key package - [Throws] - Promise add(MLSBytesOrUint8Array keyPackage); - - // Propose to Add a client to the group - // (this generates a proposal which when received will generate the - // commit output) - [Throws] - Promise proposeAdd(MLSBytesOrUint8Array keyPackage); - - // Remove a client from the group - // (For security reason self removing MUST be proposed instead!) - [Throws] - Promise remove(MLSBytesOrUint8Array remClientId); - - // Propose to Remove a client (possibly self) from the group - [Throws] - Promise proposeRemove(MLSBytesOrUint8Array remClientId); - - // Removes all users from the group apart from the client in the view - // (This could be named removeAll but self, after the commit is - // received the caller will be alone in the group and can call - // delete().) - [Throws] - Promise close(); - - // Get information about the current state of the group including - // identifier, epoch and current membership - [Throws] - Promise details(); - - // Encrypt a message to the group in the current epoch - [Throws] - Promise send(MLSBytesOrUint8ArrayOrString message); - - // Receive a message for the the current group and client identifiers - [Throws] - Promise receive(MLSBytesOrUint8Array message); - - // When a commit is generated but lost and cannot be received, the - // state can still move to the new epoch instead of calling receive on - // the commit message because we keep the pending commit in the state - [Throws] - Promise applyPendingCommit(); - - // Derive a secret for an external Application - [Throws] - Promise exportSecret(MLSBytesOrUint8ArrayOrString label, MLSBytesOrUint8Array context, unsigned long long length); - -}; - -``` - ### A more advanced example… ```javascript @@ -500,13 +290,6 @@ participants and for large groups: the cryptographic properties are that \- when \- the members of the group are honest then during that period of time you benefit from great Forward Secrecy and Post-Compromise-Security properties. -### Ongoing work - -- Alignment with other platforms such as Android -- Web Application Integrity, Consistency and Transparency effort -- Interaction with WebRTC \+ SFrame / MLS -- Get feedback to be in a good shape before submitting to standardization - ### Next steps - We will have to decide about an improved UX and UI for the long state storage, From 33d1ee4ac9b9ef53eb013c9ca7e8b0643fcbbac1 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Tue, 23 Sep 2025 17:59:31 +0200 Subject: [PATCH 13/24] Proposed solution update - added missing code --- MessagingLayerSecurity.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 946750f..d58e0e7 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -71,7 +71,7 @@ let alice = await mls.generateIdentity() let alice_credential = await mls.generateCredential(alice) // Bind the credential and indentity to one key package for alice -let alice_key_package = await mls.generateKeyPackage(alice, ac) +let alice_key_package = await mls.generateKeyPackage(alice, alice_credential) TODO: Include some code examples of client setup here. Highlight the important attributes on the client objects. ``` From c76c20f63bcbbe6a77d3f8faa646e20ae4f0f928 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Tue, 23 Sep 2025 18:08:00 +0200 Subject: [PATCH 14/24] Added draft specification/WG destination --- MessagingLayerSecurity.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index d58e0e7..9d13582 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -56,6 +56,8 @@ Our goal is to provide a simplified MLS API for Web applications. This includes basic functions for group management, such as adding and removing members. For groups, both secure messaging using the internal MLS key schedule and exporting of keying material for more advanced applications is possible. +### Usage, examples, sample code and a prose summary of how it clearly solves the problem(s) + The key notion of any messaging protocol is a client. Client is an agent that uses this protocol to establish shared cryptographic state with other clients. The client does not have to be a part of a group yet. Each client could be seen as a public indentity ("Alice", for example), a public encryption key, and a public signature key. Client credentials is a way to prove that a current member owns a specific identity (by proving the owning of the public key). The client identifier and public key -- along with any external credentials -- are often bundled into what is called a key package that is used to add clients to groups. @@ -304,7 +306,16 @@ benefit from great Forward Secrecy and Post-Compromise-Security properties. - Consider and discuss the idea of migrating the management of MLS cryptographic keys to the Credential Manager. -### Conclusion + +### Draft specification + +To be udpated + +### Incubation and/or standardization destination + +To be updated. + +### The experimental Web API for Messaging Layer Security aims to provide a robust, privacy-preserving solution for secure group communication on the web and the From ac83ea37fed5b02fe147f6db0b43697e060fa5fc Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Tue, 23 Sep 2025 18:21:15 +0200 Subject: [PATCH 15/24] Moved next steps to open questions --- MessagingLayerSecurity.md | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 9d13582..1c39031 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -292,40 +292,22 @@ participants and for large groups: the cryptographic properties are that \- when \- the members of the group are honest then during that period of time you benefit from great Forward Secrecy and Post-Compromise-Security properties. -### Next steps -- We will have to decide about an improved UX and UI for the long state storage, - and the permissions to add and clear state. -- We expect to provide **custom proposals** and **external join** features. -- We also will likely extend the API to take lists of users to Add and Remove to - reduce the number of messages to send to other participants. -- We anticipate that there will be a need for the application and users to - annotate identifiers from other users in a way that cannot be modified by - applications (e.g. to record that a user identity has been authenticated out - of bound). -- Consider and discuss the idea of migrating the management of MLS cryptographic - keys to the Credential Manager. +### Open questions +The following questions fall outside the scope of the current explainer; however, we consider it valuable to initiate a discussion on them: -### Draft specification +1) Group Storage Strategy: How do the applications plan to store groups? Should they be maintained per client, per origin, or using another approach? -To be udpated +2) API and WebCrypto Integration: Are there any advantages to allowing the API to interact directly with WebCrypto? -### Incubation and/or standardization destination +3) Performance Considerations: What performance implications should be taken into account, and what potential optimizations exist (e.g., cloning groups or adding/removing multiple users simultaneously)? -To be updated. -### +### Draft specification -The experimental Web API for Messaging Layer Security aims to provide a robust, -privacy-preserving solution for secure group communication on the web and the -internet. As this is not a web-standard, the feature has to be enabled in -about:config. +To be udpated -In parallel of this effort, Mozilla is partnering with major actors of the -industry to bring more guarantees to users when running security and privacy -critical sites through Web Application integrity, consistency and transparency -mechanisms which will help +### Incubation and/or standardization destination -By leveraging MLS and aligning with open standards, Mozilla seeks to enhance -user security and foster innovation within the web platform community. +To be updated. From 0dde80ce2875fa61e161c19760c69555b93f9b54 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Tue, 23 Sep 2025 18:24:04 +0200 Subject: [PATCH 16/24] Removed considerations --- MessagingLayerSecurity.md | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 1c39031..f1f65c6 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -256,43 +256,6 @@ console.log(await gd.details()) console.log(await ge.details()) ``` -### Notes and additional information - -**Exporting secrets for your application** - -While sending and receiving MLS application messages through the API is very -convenient, applications sometimes need to generate secrets for their own -use. These symmetric secrets can be generated via the export\_secret API -function using a specific label and context. Generating such secrets is safe and -does not expose anything about the internal secret state of the protocol as this -is done through a KDF. Note that the secret is specific to a specific epoch of -the group. - -**Partitioning and storage in the browser** - -As of now, the MLS state is stored encrypted at rest in the profile of the user, -similar to credentials so that it can later be migrated. The key for each -database is currently located in the same directory along the encrypted -database. The state is partitioned by Origin (origin+originAttributeSuffix) and -this was checked with multiple teams, including Privacy and Storage. - -**Notes on deleting MLS public and secret state** - -The MLS state for the origin (including secrets) can be deleted by the -application by calling the delete state function of the API from within this -origin. The user can also clean the state using the UI to “clear all site data” -(by clicking on the lock icon) or by calling the API via the console if they -don’t wish to clear their cookies at the same time. - -**Notes on security for large groups** - -It is often asked why anyone would think a thousand participant group could be -honest. The formal security guarantees are the same at a scale of two -participants and for large groups: the cryptographic properties are that \- when -\- the members of the group are honest then during that period of time you -benefit from great Forward Secrecy and Post-Compromise-Security properties. - - ### Open questions The following questions fall outside the scope of the current explainer; however, we consider it valuable to initiate a discussion on them: From cb5caec3dd9da8b9c31becbe11803475e4b4fe75 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Tue, 23 Sep 2025 18:24:56 +0200 Subject: [PATCH 17/24] Stylistic changed --- MessagingLayerSecurity.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index f1f65c6..bbf9839 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -94,7 +94,7 @@ let commit_added_bob = await alice_group.add(bob_key_package); // Send a message to the group let ctx = await alice_group.send(message); -// Remove a member from a group +// Remove a member from the group let commit_removed_bob = await alice_group.remove(bob); ``` From 130d448eb779bff415e52f811b8140455a88321a Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Wed, 24 Sep 2025 16:57:09 +0200 Subject: [PATCH 18/24] Extended with exporting --- MessagingLayerSecurity.md | 178 ++++++++++---------------------------- 1 file changed, 47 insertions(+), 131 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index bbf9839..82a7517 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -88,7 +88,7 @@ let alice_group = await mls.groupCreate(alice, alice_credential); let alice_group_details = await alice_group.details().members; // Invite others to the group: -// We will talk about commits and context (ctx) later in the explainer +// We will talk about commits later in the explainer let commit_added_bob = await alice_group.add(bob_key_package); // Send a message to the group @@ -99,161 +99,77 @@ let commit_removed_bob = await alice_group.remove(bob); ``` -**Key Package** +A group view represents a group from the perspective of an individual member. A group view reflects the current members of the group, the epoch (the current version of the group) as well as metadata about the group. It should be noted, however, that group views may temporarily diverge across clients if some members have not yet processed the same set of messages. -In order for users to add clients to a group, those need to -produce some encryption public key and some metadata about the ciphersuite and -extension they support for that client. This information is called a key -package. By default the API contains a function to generate those key packages -with the default parameters and extensions supported by the implementation in -Firefox. - -**Groups and GroupViews** - -Since the goal of MLS is to build and manage groups, the API is centered about -the notion of group and in particular of the GroupView object which represents -the view of a group for a specific client. The reason for this is that it is -allowed to have multiple clients in a group as long as they have different -client identifiers. Though it is an advanced feature, if multiple clients are -used in the same group, each client is able to manage its view of the group and -may process messages at different times. Each time the group evolves, a sequence -number called epoch is incremented. - -**Proposals and Commits** - -Group operations such as adding or removing users can be either proposed by -generating a proposal or the change can be made directly by generating a commit -output. Each commit output contains some information, when adding a user, it -contains a commit message, which is the information that needs to be transmitted -to existing members of the group, and a welcome message which is the information -that needs to be transmitted to the newly added client. - -### Basic usage +Application developers, including those working with the browser API, are not required to manage the low-level details of MLS directly. Instead, they interact with group views, which provide a consistent abstraction of both the group’s membership and its current state. ```javascript -let mls = new MLS() -// Create identities for alice and bob -let a = await mls.generateIdentity() -let b = await mls.generateIdentity() +// Bob joins the group +let bob_group = await mls.groupJoin(bob, commit_added_bob.welcome); -// Create credentials for alice and bob -let ac = await mls.generateCredential("alice") -let bc = await mls.generateCredential("bob") +// Bob group view and Alice group view are consistent +is (alice_group.members, bob_group.members); -// Create key packages for alice and bob -let akp = await mls.generateKeyPackage(a, ac) -let bkp = await mls.generateKeyPackage(b, bc) - -// Bob creates a group -let gb = await mls.groupCreate(b, bc) - -// Bob adds Alice to the group by using the Key Package -// (this generates a commit output which contains the welcome necessary -// to alice and the commit to update current members of the group) -let co1 = await gb.add(akp) - -// Bob uses the generated commit to update its group and immediately -// sends a message to the group (alice, bob) -let bgide1 = await gb.receive(co1.commit) -let ctx1 = await gb.send("Hello Alice!") - -// Alice uses the welcome to join the group and receives Bob's message -let ga = await mls.groupJoin(a, co1.welcome) -let pt1 = await ga.receive(ctx1) ``` -Note that, to ease testing, the code above runs both participants -but each browser will typically run one participant. - -### A more advanced example… +The changes that a member makes to its group view need to be communicated to other clients. This occurs two forms: -```javascript -// !!! -// < Insert the code for the basic example here... > -// !!! - -// Charlie creates identity keypair, credential and key package -let c = await mls.generateIdentity() -let cc = await mls.generateCredential("charlie") -let ckp = await mls.generateKeyPackage(c, cc) - -// Alice adds Charlie to the group -let co2 = await ga.add(ckp) +1) Commits – Operations that alter the state of the group, resulting in creating a message for other group participants. -// Alice and Bob process the commit which is adding Charlie -let agide2 = await ga.receive(co2.commit) -let bgide2 = await gb.receive(co2.commit) +2) Proposals - Proposal are suggestioned modifications that don't immediately change the group state. Proposals can be used when a client wants to make a change, but does not want to force the change. Maybe the client doesn't have the necessary permissions or maybe it wants to suggest something. -// Charlie joins the group and sends a message -let gc = await mls.groupJoin(c, co2.welcome) -let ctx2 = await gc.send("Hi all") - -// Alice and Bob receive charlie's message -let apt2 = await ga.receive(ctx2) -let bpt2 = await gb.receive(ctx2) - -// Charlie removes Bob from the group -let co3 = await gc.remove(b) +```javascript +// As in our example above that fact that Alice added a new member to the group created a commit +let commit_added_charlie = await alice_group.add(charlie_key_package); -// Each member receives the commit removing Bob -let agide3 = await ga.receive(co3.commit) -let bgide3 = await gb.receive(co3.commit) -let cgide3 = await gc.receive(co3.commit) +// This commit is then propagated to all the existing members to the group +let alice_group_added_charlie = await alice_group.receive(commit_added_charlie); +let bob_group_added_charlie = await bob_group.receive(commit_added_charlie); -// Alice proposes to be removed from the group -let p4 = await ga.proposeRemove(a) +// Bob does not have a right to remove Charlie, so he proposes the removal +let propose_remove_charlie = await bob_group.proposeRemove(charlie); -// Charlie processes the proposal and generates a commit output -let co4 = await gc.receive(p4) +// Alice does have a right to remove Charlie, so she generates a commit +let commit_remove_charlie = await alice_group.receive(propose_remove_charlie); +// This commit (commit_remove_charlie) will be send to all the participants -// Alice and Charlie process the commit to remove Alice -let agide4 = await ga.receive(co4.commitOutput.commit) -let cgide4 = await gc.receive(co4.commitOutput.commit) +``` -// Generate identities, credentials and key packages for -// delphine and ernest -let d = await mls.generateIdentity() -let e = await mls.generateIdentity() -let dc = await mls.generateCredential("delphine") -let ec = await mls.generateCredential("ernest") -let dkp = await mls.generateKeyPackage(d, dc) -let ekp = await mls.generateKeyPackage(e, ec) +Each modification to the group results in an increment of the epoch. -// Charlie adds Delphine to the Group and process the commit -let co5 = await gc.add(dkp) -let cgide5 = await gc.receive(co5.commit) -// Delphine uses the welcome to join the group -let gd = await mls.groupJoin(d, co5.welcome) +```javascript +// The group view epochs are constistent between the members +is (alice_group.epoch, bob_group.epoch); -// Delphine proposes to add Ernest to the group -let p6 = await gd.proposeAdd(ekp) +// All the participants received the same commit +let alice_group_after_commit = await alice_group.receive(some_commit); +let bob_group_after_commit = await bob_group.receive(some_commit); -// Charlie generate a commit output for Delphine's proposa to add Ernest -let rec6 = await gc.receive(p6) +// The group views are consistent after receiving the same commit +is (alice_group_after_commit.epoch, bob_group_after_commit.epoch) +// The epoch got incremented after receiving the commit. +is (inc(alice_group.epoch), alice_group_after_commit) -// Charlie and Delphine process the commit to add Ernest -let cgide6 = await gc.receive(rec6.commitOutput.commit) -let dgide6 = await gd.receive(rec6.commitOutput.commit) +``` -// Ernest joins the group -let ge = await mls.groupJoin(e, rec6.commitOutput.welcome) +Since MLS is not solely a protocol for confidential group messaging but also serves as a foundation for secure group communication more broadly, certain applications may require additional cryptographic keys beyond the one used for message encryption. For example, secure file sharing would require a separate encryption key. To address this requirement, MLS provides a mechanism for deriving (exporting) keys. -// Create exporter labels and context ("context" in ASCII) -const context_bytes = new Uint8Array([99, 111, 110, 116, 101, 120, 116]); const exporter_len = 32; +```javascript +// The group views are constistent between the members +is (alice_group, bob_group); -// Ernest generates an exporter secret -let exporterOutput = await ge.exportSecret( - "label", context_bytes, exporter_len); +// Alice and Bob derive a key to be used for file sharing +// For learning more about context, please check RFC 9420 +let exporter_alice = await alice_group.exportSecret("file sharing key", context_for_file_id_and_epoch, len); +let exporter_bob = await bob_group.exportSecret("file sharing key", context_for_file_id_and_epoch, len); -// This is the shared secret for the group at this epoch -let secret = exporterOutput.secret; +// The keys are equal for consistent groups +is (exporter_alice, exporter_bob) -// Display group information for all group views -console.log(await gc.details()) -console.log(await gd.details()) -console.log(await ge.details()) +// And the keys for different label ("file sharing key") or context would not be the same +// This ensures FS and PCS even for derived keys ``` ### Open questions @@ -269,7 +185,7 @@ The following questions fall outside the scope of the current explainer; however ### Draft specification -To be udpated +To be updated. ### Incubation and/or standardization destination From 7f4d66458c5ef126542763df1b0c17eaa834ee27 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Wed, 24 Sep 2025 17:00:51 +0200 Subject: [PATCH 19/24] Stylistic changes --- MessagingLayerSecurity.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 82a7517..3d94b58 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -115,9 +115,9 @@ is (alice_group.members, bob_group.members); The changes that a member makes to its group view need to be communicated to other clients. This occurs two forms: -1) Commits – Operations that alter the state of the group, resulting in creating a message for other group participants. +1) Commits: Operations that alter the state of the group, resulting in creating a message for other group participants. -2) Proposals - Proposal are suggestioned modifications that don't immediately change the group state. Proposals can be used when a client wants to make a change, but does not want to force the change. Maybe the client doesn't have the necessary permissions or maybe it wants to suggest something. +2) Proposals: Proposal are suggestioned modifications that don't immediately change the group state. Proposals can be used when a client wants to make a change, but does not want to force the change. Maybe the client doesn't have the necessary permissions or maybe it wants to suggest something. ```javascript // As in our example above that fact that Alice added a new member to the group created a commit From fc945fc71c98fc7586ebc4d1916fa85418199726 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Wed, 24 Sep 2025 17:01:11 +0200 Subject: [PATCH 20/24] Stylistic changes --- MessagingLayerSecurity.md | 1 + 1 file changed, 1 insertion(+) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 3d94b58..1b969d4 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -149,6 +149,7 @@ let bob_group_after_commit = await bob_group.receive(some_commit); // The group views are consistent after receiving the same commit is (alice_group_after_commit.epoch, bob_group_after_commit.epoch) + // The epoch got incremented after receiving the commit. is (inc(alice_group.epoch), alice_group_after_commit) From 3a6f69cbba6b43c0d46a2a498e6b4ac17eb1fb9b Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Wed, 24 Sep 2025 17:09:00 +0200 Subject: [PATCH 21/24] Stylistic changes --- MessagingLayerSecurity.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 1b969d4..2b0f805 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -58,9 +58,9 @@ This includes basic functions for group management, such as adding and removing ### Usage, examples, sample code and a prose summary of how it clearly solves the problem(s) -The key notion of any messaging protocol is a client. Client is an agent that uses this protocol to establish shared cryptographic state with other clients. The client does not have to be a part of a group yet. +The key notion of any messaging protocol is a client. Client is an agent that uses this protocol to establish a shared cryptographic state with other clients. The client does not have to be a part of a group yet. -Each client could be seen as a public indentity ("Alice", for example), a public encryption key, and a public signature key. Client credentials is a way to prove that a current member owns a specific identity (by proving the owning of the public key). The client identifier and public key -- along with any external credentials -- are often bundled into what is called a key package that is used to add clients to groups. +Each client could be seen as a public identity ("Alice", for example), a public encryption key, and a public signature key. Client credentials is a way to prove that a current member owns a specific identity (by proving the owning of the public key). The client identifier and public key -- along with any external credentials -- are often bundled into what is called a key package that is used to add clients to groups. ```javascript @@ -72,13 +72,13 @@ let alice = await mls.generateIdentity() // Create credential for alice let alice_credential = await mls.generateCredential(alice) -// Bind the credential and indentity to one key package for alice +// Bind the credential and identity to one key package for alice let alice_key_package = await mls.generateKeyPackage(alice, alice_credential) TODO: Include some code examples of client setup here. Highlight the important attributes on the client objects. ``` -Groups are collection of users. Each client included in a group is a member of the group. Each group member has access to the group's secrets. +Groups are a collection of users. Each client included in a group is a member of the group. Each group member has access to the group's secrets. ```javascript // A user could create a group @@ -117,7 +117,7 @@ The changes that a member makes to its group view need to be communicated to oth 1) Commits: Operations that alter the state of the group, resulting in creating a message for other group participants. -2) Proposals: Proposal are suggestioned modifications that don't immediately change the group state. Proposals can be used when a client wants to make a change, but does not want to force the change. Maybe the client doesn't have the necessary permissions or maybe it wants to suggest something. +2) Proposals: Proposals are suggested modifications that don't immediately change the group state. Proposals can be used when a client wants to make a change, but does not want to force the change. Maybe the client doesn't have the necessary permissions or maybe it wants to suggest something. ```javascript // As in our example above that fact that Alice added a new member to the group created a commit @@ -140,7 +140,7 @@ Each modification to the group results in an increment of the epoch. ```javascript -// The group view epochs are constistent between the members +// The group view epochs are consistent between the members is (alice_group.epoch, bob_group.epoch); // All the participants received the same commit @@ -158,7 +158,7 @@ is (inc(alice_group.epoch), alice_group_after_commit) Since MLS is not solely a protocol for confidential group messaging but also serves as a foundation for secure group communication more broadly, certain applications may require additional cryptographic keys beyond the one used for message encryption. For example, secure file sharing would require a separate encryption key. To address this requirement, MLS provides a mechanism for deriving (exporting) keys. ```javascript -// The group views are constistent between the members +// The group views are consistent between the members is (alice_group, bob_group); // Alice and Bob derive a key to be used for file sharing From 24d40a01c5fc8ccc8858d1eb19c89b1e565178e4 Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Thu, 25 Sep 2025 14:32:44 +0200 Subject: [PATCH 22/24] Addressed reviewers comments --- MessagingLayerSecurity.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index 2b0f805..d310d02 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -8,9 +8,9 @@ Last updated: September 23, 2025 -The Messaging Layer Security (MLS) standard ([RFC 9420](https://www.rfc-editor.org/rfc/rfc9420.html)) addresses the challenges of scalable, efficient, and standardized end-to-end encryption for group messaging, while ensuring critical security properties such as forward secrecy (FS), post-compromise security (PCS) for groups with more than two participants. +The Messaging Layer Security (MLS) standard ([RFC 9420](https://www.rfc-editor.org/rfc/rfc9420.html)) addresses the challenges of scalable, efficient, and standardized end-to-end encryption for group messaging, while ensuring critical security properties such as forward secrecy (FS), post-compromise security (PCS) for groups with more than two participants. -The standard has already attracted significant attention, with several major vendors expressing interest in implementing it within their products. Providing a single, standardized, and interoperable approach would offer substantial benefits to messaging application developers as well as the organisations willing to deploy MLS-based communication facilities, enabling them to deliver native, secure messaging support on the web efficiently and reliably. Once supported across all major browsers, developers would be able to write the integration code once and have it work consistently across platforms, significantly reducing development complexity and improving reliability. +The standard has already attracted significant attention, with several major vendors expressing interest in implementing it within their products. Providing a single, standardized, and interoperable approach would offer substantial benefits to messaging application developers as well as the organisations willing to deploy MLS-based communication facilities. Ultimately enabling them to deliver native, secure messaging support on the web efficiently and reliably. Once supported across all major browsers, developers would be able to write the integration code once and have it work consistently across platforms, which in turn would significantly reduce development complexity and improve reliability. ### Methodology for approaching & evaluating solutions @@ -42,23 +42,23 @@ Several existing initiatives aim to address the stated user problem. 4) Messaging Layer Security over ActivityPub [draft report](https://swicg.github.io/activitypub-e2ee/mls) describes the interfaces between MLS and ActivityPub. +5) [Discord](https://www.thestack.technology/discord-encryption-mls-e2ee/) already uses MLS in their products. + ### Flaws or limitations in existing features/proposals that prevent solving the problem(s) -None of the aforementioned features directly address the challenge of establishing a single, unified standard. +However, none of the aforementioned features directly address the challenge of establishing a single, unified standard. ### Motivation for this explainer, why we think we can do better than the status quo or other proposals -We believe that a single, standardized Web API can significantly improve implementation quality by providing an interface that is both resistant to misuse and easy to implement. We also consider that focusing on a limited set of core functions would create a simpler, more approachable , and less error-prone interface. +We believe that a single, standardized Web API can significantly improve implementation quality and counter interoperability problems by providing an interface that is both resistant to misuse and easy to implement. We also consider that focusing on a limited set of core functions will create a simpler, more approachable, and less error-prone interface. ### Outline of a proposed solution -Our goal is to provide a simplified MLS API for Web applications. - -This includes basic functions for group management, such as adding and removing members. For groups, both secure messaging using the internal MLS key schedule and exporting of keying material for more advanced applications is possible. +Our goal is to provide a simplified MLS API for Web applications.This includes basic functions for group management, such as creating members, creating groups, adding and removing members, and exporting keys. For groups, both secure messaging using the internal MLS key schedule and exporting of keying material for more advanced applications is possible. ### Usage, examples, sample code and a prose summary of how it clearly solves the problem(s) -The key notion of any messaging protocol is a client. Client is an agent that uses this protocol to establish a shared cryptographic state with other clients. The client does not have to be a part of a group yet. +The key notion of any messaging protocol is a client. A client is an agent that uses this protocol to establish a shared cryptographic state with other clients. The client does not have to be a part of a group yet. Each client could be seen as a public identity ("Alice", for example), a public encryption key, and a public signature key. Client credentials is a way to prove that a current member owns a specific identity (by proving the owning of the public key). The client identifier and public key -- along with any external credentials -- are often bundled into what is called a key package that is used to add clients to groups. From 3f87ffafe5a081ae17a32961533c73b395dc196e Mon Sep 17 00:00:00 2001 From: Anna Weine Date: Thu, 25 Sep 2025 14:39:58 +0200 Subject: [PATCH 23/24] Remove Benjamin WAICT modification --- waict-explainer.md | 101 --------------------------------------------- 1 file changed, 101 deletions(-) delete mode 100644 waict-explainer.md diff --git a/waict-explainer.md b/waict-explainer.md deleted file mode 100644 index f14c616..0000000 --- a/waict-explainer.md +++ /dev/null @@ -1,101 +0,0 @@ -# WAICT (Web Application Integrity, Consistency, and Transparency) - -## 1. What Are We Doing? -We aim to **raise the security and privacy bar for web applications** by ensuring three key properties: - -1. **Integrity**: Prevent any unauthorized modification of site code—even if served by a third-party CDN. -2. **Consistency**: Give users confidence that they receive the *same* code everyone else does (i.e., no user-specific malicious versions). -3. **Transparency**: Ensures stronger security for the Consistency mechanism. Encourage append-only logs that record published code versions, deterring hidden or short-lived changes and helping external audits. - -Our goal is a **standardized, browser-based mechanism** that sites can easily opt into—without forcing users to install extensions. While we propose high-level strategy and a technical proposal here, **technical details remain open for discussion** among browser vendors, web application providers, and standards bodies. - ---- - -## 2. Why Are We Doing This? -### Security-Critical Applications -Webmail, secure messaging, banking, and other sensitive sites face *strong* threats: -- **Insider Threats**: Malicious insiders, internal bugs, or selective content modifications. -- **Hosting Compromises**: Attackers or misconfigurations can serve altered code. - -### User Trust -This is particularly vital for end-to-end encryption: the page’s integrity is the most important part of the security chain. (because it's encrypted everywhere else, the endpoints are the weak link, so ensuring security is strong there is paramount) - -### Extensions & Explicit Consent -Currently, only specialized browser extensions (like CodeVerify) can provide stronger assurances. But extensions require extra user steps, limiting adoption. Our approach makes these protections native and more widely available. - ---- - -## 3. How Are We Doing This? -1. **Leverage & Extend SRI** - - Instead of a per-resource hash, we propose a **manifest-based** approach listing all subresources (script, style, etc.) with, typically, a single signature covering the manifest to remove performance problems. - -2. **HTTP Header (possibly an extension of CSP)** - - Introduce an “integrity-manifest” directive to specify: - - **Where** the browser fetches the manifest (`integrity-manifest-src`). - - **How** strictly to enforce integrity (`integrity-enforcement-level`). - - If necessary raise UI or block the page based on the enforcement level. - -3. **Add Transparency & Consistency** - - **Signed Manifests & Logs**: Sites can embed cryptographic proof of logging each manifest into an append-only record. - - **Proof of Inclusion**: Browsers verify that they trust the proof of inclusion but do not need to look into the content. The auditability prevents stealth “one-off” versions. - - **Downgrade Prevention**: Once a domain is known to enforce these policies, it can request browsers to not accept weaker modes for a specific amount of time (not exactly like, but similar to HSTS). - -4. **Prototype & Standardize** - - We’ll refine prototypes through collaboration with major actors (e.g., WebAppSec at W3C) and consider parallel IETF work for the logging/transparency pieces. - - **Implementation details** though we want to align on the high level information to raise to the user (if any), this should likely remain implementation specific on the browser side. - ---- - -## 4. Why Integrity and Transparency Together? -- **Short Attack Windows**: Without transparency, a malicious version can appear briefly and vanish with minimal trace. It could achieve local consistency even if checked through multiple network paths. -- **Stronger Deterrence**: A public log, plus manifest-based integrity, makes *every* release visible. Hiding malicious changes becomes much riskier. -- **Efficient Cohesion**: Designing them simultaneously avoids redundant or conflicting mechanisms and simplifies adoption for large, dynamic sites. - ---- - -## 5. Why We Think We Can Actually Do This -- **Real Precedent: CodeVerify** - - Meta built an extension verifying scripts for WhatsApp, Instagram, and Messenger. It works in production, used by actual users, proving feasibility-though it remains optional and partial. -- **Scalability for Large Sites** - - Our manifest approach is explicitly designed for high-traffic, multi-CDN services and A/B testing. -- **Browser & Site Interest** - - Multiple vendors have indicated willingness to explore and prototype stronger security. -- **Incremental Adoption** - - Non-participating sites are unaffected. Early adopters can start with basic script integrity and then expand to styles, WASM, or further subresources. They can also choose to deploy different enforcement levels and/or enable the downgrade protection gradually. - ---- - -## 6. Why Aren’t SRI or CodeVerify Sufficient on Their Own? -1. **Subresource Integrity (SRI)** - - **Limitations**: Requires distinct hashes colocated for every resource; large sites find this unwieldy. It also *does not* provide transparency or consistency assurances. It is restricted to scripts at this time. SRI also provides no inclusion or exclusion benefits on the set of scripts. This might be included in transparency, as it governs the addition or removal of scripts for individual users or page loads. Similarily, import-map-integrity only covers ES modules and not packages and Sig-based SRI is too costly for large sets of resources and doesn't cover Consistency... -2. **CodeVerify Extension** - - **Limitations**: Relies on user installation, cannot verify all resource types, and remains out-of-band from standard browser features. Browser Extension APIs are insufficent for strong protections. - -By integrating such ideas *natively*—with a manifest-based approach plus transparency logs—we bring increased default security to all users without requiring an extension. - ---- - -## 7. Who Needs It, and Who Will Deploy It? -- **Needs It** - - **High-Security Apps**: Secure messaging, financial portals, healthcare sites. - - **Smaller Sites**: Quickly benefit from the same protections with minimal overhead. -- **Willing to Implement** - - **Browser Vendors**: Indicated interest in providing a standard solution to solve the strategic security objective. Firefox is invested in the topic and would ideally prefer to implement a standard. - - **Large Content Providers**: Entities serving traffic eg. Cloudflare or Critical sites like Meta’s Facebook, WhatsApp, Instagram sites. - ---- - -## 8. Conclusion and Next Steps -We propose a **two-phase** approach: -1. **Integrity**: Extend SRI with a manifest-based signature approach and a header to announce the integrity configuration. -2. **Consistency & Transparency**: Integrate cryptographic proofs and public logging to deter targeted attacks and enable long-term audits. - -Our next steps include **prototyping** these mechanisms, collaborating across browsers and large-scale websites, and preparing a draft for standardization in W3C WebAppSec and possibly IETF. We want to **align on the high-level strategic idea** that browsers can natively enforce integrity, consistency, and transparency—while acknowledging that **the specifics of this proposal remain open to technical debate**. - -By designing integrity and transparency together, we can make the web more trustworthy, ensuring that all users can rely on security-critical sites to deliver the code they promise, consistently and visibly. - ---- - -## 9. More details - -You can find more details in [this document](https://docs.google.com/document/d/16-cvBkWYrKlZHXkWRFvKGEifdcMthUfv-LxIbg6bx2o). From 8855b7fb567770170caa59f9839a2affc757fae1 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 1 Oct 2025 04:13:54 -1000 Subject: [PATCH 24/24] Add space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tantek Çelik <46418+tantek@users.noreply.github.com> --- MessagingLayerSecurity.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MessagingLayerSecurity.md b/MessagingLayerSecurity.md index d310d02..a5fcd15 100644 --- a/MessagingLayerSecurity.md +++ b/MessagingLayerSecurity.md @@ -54,7 +54,7 @@ We believe that a single, standardized Web API can significantly improve impleme ### Outline of a proposed solution -Our goal is to provide a simplified MLS API for Web applications.This includes basic functions for group management, such as creating members, creating groups, adding and removing members, and exporting keys. For groups, both secure messaging using the internal MLS key schedule and exporting of keying material for more advanced applications is possible. +Our goal is to provide a simplified MLS API for Web applications. This includes basic functions for group management, such as creating members, creating groups, adding and removing members, and exporting keys. For groups, both secure messaging using the internal MLS key schedule and exporting of keying material for more advanced applications is possible. ### Usage, examples, sample code and a prose summary of how it clearly solves the problem(s)