| Internet-Draft | FSMLS | March 2026 |
| Robert & Kohbrok | Expires 3 September 2026 | [Page] |
This draft specifies modified versions of MLS KeyPackage messages, as well as MLS PublicMessages and PrivateMessages holding Commits or Update Proposals that require one less signature than their original counterparts.¶
This note is to be removed before publishing as an RFC.¶
The latest revision of this draft can be found at https://kkohbrok.github.io/draft-kohbrok-single-signature-keypackages/draft-kohbrok-mls-fewer-signatures.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-kohbrok-mls-fewer-signatures/.¶
Discussion of this document takes place on the Messaging Layer Security Working Group mailing list (mailto:mls@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/mls/. Subscribe at https://www.ietf.org/mailman/listinfo/mls/.¶
Source for this draft and an issue tracker can be found at https://github.com/kkohbrok/draft-kohbrok-single-signature-keypackages.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 3 September 2026.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Both MLS KeyPackage messages, as well as PublicMessages and PrivateMessages holding Commits and Update Proposals can be safely sent with one fewer signature than specified in [RFC9420], although the latter two only if certain conditions are met.¶
Regular MLS KeyPackages require two signatures: One over the LeafNode and one over the KeyPackage around it. This draft introduces a LeafNode component that contains a hash over the KeyPackage fields surrounding the LeafNode. As a consequence, verifying the LeafNode also verifies the KeyPackage.¶
For Commits with an UpdatePath or Update Proposals (sent as PublicMessage or PrivateMessage) the issue is similar: One signature covers the LeafNode and one signature covers the majority of the struct that ends up being sent over the wire. This draft proposes new types of PublicMessage and PrivateMessage with only one signature, although the signature can only be omitted for Commits that contain an UpdatePath and for Commits and Update Proposals if the LeafNode doesn't change the sender's signature public key.¶
Saving a signature can result in a significant decrease in computational or bandwidth cost, especially in the context of PQ-secure signature schemes such as ML-DSA, where signatures are multiple orders of magnitude larger than those of most non-PQ signature schemes.¶
This document specifies three new entries for the IANA WireFormat registry, which results in the following changes to the MLSMessage struct as defined in [RFC9420].¶
struct {
...
select (MLSMessage.wire_format) {
...
case mls_os_key_package:
OneSignatureKeyPackage key_package;
case mls_os_private_message:
OSPrivateMessage private_message;
case mls_os_public_message:
OSPublicMessage public_message;
};
} MLSMessage;
¶
See Section 3 for the definition of OneSignatureKeyPackage and Section 4 for the definitions of OSPrivateMessage and OSPublicMessage.¶
A OneSignatureKeyPackage functions like a regular KeyPackage, except that it's partitioned into two components: The OuterKeyPackage and the LeafNode. The OuterKeyPackage contains all fields of a regular KeyPackage except the LeafNode and the signature.¶
struct {
ProtocolVersion version;
CipherSuite cipher_suite;
HPKEPublicKey init_key;
Extension extensions<V>;
} OuterKeyPackage
struct {
OuterKeyPackage outer_key_package;
LeafNode leaf_node;
} OneSignatureKeyPackage
¶
A OneSignatureKeyPackage is created like a regular KeyPackage with the following exceptions.¶
The signature around the outer KeyPackage is omitted¶
An app_data_dictionary extension is added to the LeafNode (if not already
present)¶
An OuterKeyPackageHash component is included in the app_data_dictionary (see
Section 3.2)¶
The original purpose of the signature over the KeyPackage is now served by the signature over the LeafNode, which by inclusion of the OuterKeyPackageHash provides authenticity for both the LeafNode itself and the OuterKeyPackage around it.¶
struct {
opaque outer_key_package_hash;
} OuterKeyPackageHash
¶
The OuterKeyPackageHash can be created by hashing the TLS-serialized
outer_key_package of a OneSignatureKeyPackage using the hash function of its
ciphersuite.¶
A OuterKeyPackageHash is only valid if two conditions are met.¶
Recipients of a OneSignatureKeyPackage process is like a regular KeyPackage with two exceptions¶
There is no signature over the outer KeyPackage to verify¶
The app_data_dictionary extension in the leaf_node must contain a valid
OuterKeyPackageHash as defined in Section 3.2 under the
component_id TBD.¶
MLS PublicMessages and PrivateMessages carrying a Commit with UpdatePath or an Update Proposal can also be created with only one signature as long as the signature key of the sender is not changed by the respective operation. The resulting structs are called OSPublicMessage and OSPrivateMessage respectively.¶
The principle behind saving the signature is the same as for OneSignatureKeyPackage. The signature over the whole struct is omitted and instead a hash over the otherwise signed part of the struct (minus the LeafNode) is placed as a component in the LeafNode of the UpdatePath or the Update Proposal.¶
The core change in framing an OSPublicMessage or OSPrivateMessage as compared to its regular counterparts is that the FramedContentAuthData is replaced by the OSFramedContentAuthData, where the latter lacks the signature that is part of the former. Other framing structs are changed as a result in that they contain an OSFramedContentAuthData struct instead of a FramedContentAuthData struct.¶
struct {
select (FramedContent.content_type) {
case commit:
/*
MAC(confirmation_key,
GroupContext.confirmed_transcript_hash)
*/
MAC confirmation_tag;
case application:
case proposal:
struct{};
};
} OSFramedContentAuthData;
struct {
WireFormat wire_format;
FramedContent content;
OSFramedContentAuthData auth;
} OSAuthenticatedContent;
struct {
select (PrivateMessage.content_type) {
case application:
opaque application_data<V>;
case proposal:
Proposal proposal;
case commit:
Commit commit;
};
OSFramedContentAuthData auth;
opaque padding[length_of_padding];
} OSPrivateMessageContent;
struct {
FramedContent content;
OSFramedContentAuthData auth;
select (PublicMessage.content.sender.sender_type) {
case member:
MAC membership_tag;
case external:
case new_member_commit:
case new_member_proposal:
struct{};
};
} OSPublicMessage;
¶
The structs involved in membership tag and transcript hash computation also change slightly.¶
struct {
FramedContentTBS content_tbs;
OSFramedContentAuthData auth;
} OSAuthenticatedContentTBM;
¶
For OSPublicMessages, the membership_tag is computed over
OSAuthenticatedContentTBM instead of the regular AuthenticatedContentTBM.¶
struct {
WireFormat wire_format;
FramedContent content; /* with content_type == commit */
} OSConfirmedTranscriptHashInput;
¶
Due to the changes in framing, the transcript hash for OSPublicMessages and
OSPrivateMessages is computed over OSConfirmedTranscriptHashInput instead of the
regular ConfirmedTranscriptHash. Since the LeafNode is within FramedContent and
its signature covers what the original signature would have covered, this does
not affect transcript coverage.¶
The OuterUpdateHash component ensures that the signature over the LeafNode covers whatever the omitted signature would have covered.¶
struct {
opaque outer_update_hash;
} OuterUpdateHash
struct {
opaque group_id<V>;
uint64 epoch;
Sender sender;
opaque authenticated_data<V>;
ContentType content_type;
select (FramedContent.content_type) {
case proposal:
ProposalType proposal_type;
case commit:
ProposalOrRef proposals<V>;
UpdatePathNode nodes<V>;
case application:
struct {};
};
} OuterFramedContent
struct {
ProtocolVersion version = mls10;
WireFormat wire_format;
OuterFramedContent content;
GroupContext context;
} OSFramedContentTBH
¶
The outer_update_hash MUST be a hash over the message's TLS-serialized
OSFramedContentTBH using the hash function of the group's ciphersuite.¶
OSFramedContentTBH is the same as the FramedContentTBS struct defined in
[RFC9420], except that it always contains a GroupContext (because Commits and
Update Proposals only have member or new_member_commit as sender_type) and
that it contains an OuterFramedContent instead of a regular FramedContent.¶
OuterFramedContent in turn is the same as FramedContent except that, depending
on content_type, it either contains only content relevant to a Commit with an
UpdatePath or an Update Proposal. For Commits, the proposals MUST be the same
as in the message's Commit and the nodes MUST be equal to the nodes in the
Commit's UpdatePath. For Update Proposals, the proposal_type MUST be update.
The proposal type is the only relevant content, as the Update Proposal otherwise
only consists of the (omitted) LeafNode.¶
In both cases, the actual LeafNode is omitted to prevent a circular dependency
when computing the outer_update_hash for inclusion in said LeafNode.¶
Clients create an OSPublicMessage or OSPrivateMessage just like their non-OS counterpart with three exceptions:¶
The signature in FramedContentData is omitted by using OSFramedContentData and the other modified structs introduced in Section 4.1 instead of their non-OS counterparts.¶
An app_data_dictionary is included in the LeafNode (either in the UpdatePath
or the Update Proposal) and within it an OuterUpdateHash component (see
Section 4.3).¶
The membership tag and transcript hash are computed as specified in Section 4.2.¶
OSPublicMessages and OSPrivateMessages are processed like their regular counterparts with the following exceptions.¶
One of the following MUST be true¶
The signature public key in the LeafNode MUST be the same as the sender's
current LeafNode. This MUST also be true for Commits with sender_type =
new_member_commit that contain a Remove Proposal targeting the sender's
original leaf.¶
The LeafNode (either in the UpdatePath or in the Update Proposal) MUST contain
an app_data_dictionary extension with a valid OuterUpdateHash component as
specified in Section 4.3.¶
Membership tag and transcript hash are computed as specified in Section 4.2.¶
The second check for signature public key equality is necessary to ensure that the authentication properties of one-signature message variants are equivalent to their counterparts defined in RFC9420. Clients that want to change their signature public key MUST use the normal (external) Commits and Update Proposals to ensure that the new signature public key is signed by the old one.¶
Security considerations around the one signature variants are the same as those of their regular MLS counterparts, except their content should not be trusted until the signature of the LeafNode was verified and the OuterKeyPackageHash or OuterUpdateHash component was validated.¶
This document requests the addition of two new Component Types under the heading of "Messaging Layer Security".¶
The OuterKeyPackageHash component contains a hash over the outer parts of a OneSignatureKeyPackage.¶
This document requests the addition of three new WireFormats under the heading of "Messaging Layer Security".¶
The mls_os_key_package allows saving the creation and
verification of a signature that is necessary when creating a regular
KeyPackage.¶
The mls_os_private_message allows saving the creation and
verification of a signature that is necessary when creating a regular
PrivateMessage that either contains a Commit with an UpdatePath or an Update
Proposal.¶
The mls_os_public_message allows saving the creation and
verification of a signature that is necessary when creating a regular
PublicMessage that either contains a Commit with an UpdatePath or an Update
Proposal.¶
TODO acknowledge.¶