jiebi/CodeConvo huggingface dataset:
Change:
This suggestion is based on a discussion in the MLS mailing list . It prevents issues that currently arrise when the very first commit of a group is an "add-only" commit because both the and would be 0. Let me know if the wording or anything else should be changed. /cc NAME URL
I believe this change invalidates the last paragraph of the , as it is impossible to verify the group creation process for the joiner without knowing the random that the group creator used.
maybe one alternative is to keep the zero , but make it compulsory to populate the path for this group creation welcome/commit (so that isn't zero)?
That would also work NAME (I also suggested that as an alternative in my original report in the mailing list), to me it is a little bit less elegant though. Personally, I also wonder why it is necessary to verify that group creation just happened. (Moreover, this way of recognizing group creation would prevent any group from which all but one person left from continuing, which my be confusing to end-users)
lgtm with one minor thing fixed Hi Eric, Thanks for the analysis, and the detailed, clear writeup. I agree that there are some real issues here, and with the solution approach. Just to align on a couple of details: is clearly a problem. Good catch. is less clear to me. You lose me when you say ""add-only" commits allow new group members (ONLY) to learn the value at the root of the TreeKEM tree". How do you think this happens? As I understand the spec, this is not the case. New members are added to the "unmergedleaves" array at the root, but they are not told the root secret or root private key. In any case, I agree that we should change the initial initsecret from being zero to being random. I think I had set it to zero out of a general caution against requiring fresh entropy, and likely under the theory that the first commit would change it (before was optional). But it is clearly necessary now. If you would like to send a PR, I would be happy to review. Thanks, --Richard >

Discussion:
Interim transcript hash: 0 <del> Init secret: 0 </del> <ins> Init secret: a fresh random value of size "KDF.Nh" </ins> For each member, construct an Add proposal from the KeyPackage for that member (see add)
Change:
Addresses ambiguity pointed out on the mailing list by NAME
In , we changed from using HKDF to using the KDF from HPKE, which I thought removed the need for the ciphersuite to specify a hash function. As a result, ciphersuites no longer needed to specify a hash. However, the transcript computations still have a raw invocation, not a KDF invocation. So we need to either: Change the transcript hash computations to use the KDF, or Clarify that ciphersuites still specify a hash function (as before)
What about the call in the and the "hashes" for ?

Discussion:
members to incorporate a Commit message into the transcript without having to store the whole MLSPlaintextCommitAuthData structure. <del> When a new group is created, the "interim_transcript_hash" field is set to the zero-length octet string. </del> <ins> As shown above, when a new group is created, the "interim_transcript_hash" field is set to the zero-length octet string. </ins> 7.7.

These ciphersuites map to HPKE primitives and TLS signature schemes as follows I-D.irtf-cfrg-hpke RFC8446: <ins> The hash used for the MLS transcript hash is the one referenced in the ciphersuite name.  In the ciphersuites defined above, "SHA256" and "SHA512" refer to the SHA-256 and SHA-512 functions defined in SHS. </ins> It is advisable to keep the number of ciphersuites low to increase the chances clients can interoperate in a federated environment, therefore the ciphersuites only inlcude modern, yet well-established
Change:
This PR gets rid of the explicit HMAC reference and uses KDF.Extract instead (which internally uses HMAC). Also is renamed to .
I don't love the extra , but I can live with it.

Discussion:
Thus the "confirmed_transcript_hash" field in a GroupContext object represents a transcript over the whole history of MLSPlaintext Commit <del> messages, up to the confirmation field in the current MLSPlaintext message.  The confirmation and signature fields are then included in the transcript for the next epoch.  The interim transcript hash is passed to new members in the GroupInfo struct, and enables existing members to incorporate a Commit message into the transcript without having to store the whole MLSPlaintextCommitAuthData structure. </del> <ins> messages, up to the confirmation tag field in the current MLSPlaintext message.  The confirmation tag and signature fields are then included in the transcript for the next epoch.  The interim transcript hash is passed to new members in the GroupInfo struct, and enables existing members to incorporate a Commit message into the transcript without having to store the whole MLSPlaintextCommitAuthData structure. </ins> As shown above, when a new group is created, the "interim_transcript_hash" field is set to the zero-length octet

Construct an MLSPlaintext object containing the Commit object. Use the "commit_secret" to advance the key schedule and compute <del> the "confirmation" value in the MLSPlaintext.  Sign the </del> <ins> the "confirmation_tag" value in the MLSPlaintext.  Sign the </ins> MLSPlaintext using the current epoch's GroupContext as context. Update the tree in the provisional state by applying the direct

Group ID, epoch, tree, confirmed transcript hash, and interim transcript hash from the new state <del> The confirmation from the MLSPlaintext object </del> <ins> The confirmation_tag from the MLSPlaintext object </ins> Sign the GroupInfo using the member's private signing key

and derived secrets for the new epoch. Use the "confirmation_key" for the new epoch to compute the <del> confirmation MAC for this message, as described below, and verify that it is the same as the "confirmation" field in the </del> <ins> confirmation tag for this message, as described below, and verify that it is the same as the "confirmation_tag" field in the </ins> MLSPlaintext object. If the above checks are successful, consider the updated GroupContext object as the current state of the group. <del> The confirmation value confirms that the members of the group have arrived at the same state of the group: HMAC RFC2104 uses the Hash algorithm for the ciphersuite in use. </del> <ins> The confirmation tag value confirms that the members of the group have arrived at the same state of the group: </ins> 10.2.1.

Set the confirmed transcript hash in the new state to the value of the "confirmed_transcript_hash" in the GroupInfo. <del> Verify the confirmation MAC in the GroupInfo using the derived </del> <ins> Verify the confirmation tag in the GroupInfo using the derived </ins> confirmation key and the "confirmed_transcript_hash" from the GroupInfo.
Change:
As discussed on this removes the paragraph in the Group Creation section specifying that joiners SHOULD verify group creation if it is detected. A recent change to group creation - namely a random initial - makes it impossible to verify group creation.
URL Hi Eric, I agree with (2). I think the stuff that's in the spec right now about verifying group creation is mainly just a legacy of the fact that we used to have separate Init and Add operations. When those got coalesced into Welcome, it must have seemed appealing to enable recipients to continue to distinguish the cases. But as you point out, that's not really tenable. So please feel free to send a PR! Thanks, --Richard Cornelissen Eric wrote:

Discussion:
KeyPackage, the leaf secret from which the Commit is built, and the intermediate key pairs along the direct path to the root. <del> A new member receiving a Welcome message can recognize group creation if the number of entries in the "members" array is equal to the number of leaves in the tree minus one.  A client receiving a Welcome message SHOULD verify whether it is a newly created group, and if so, SHOULD verify that the above process was followed by reconstructing the Add and Commit messages and verifying that the resulting transcript hashes and epoch secret match those found in the Welcome message. </del> 10. Over the lifetime of a group, its membership can change, and existing
Change:
The public key in a credential is introduced without a special name and the field in the BasicCredential is currently called public_key, which is not very expressive. A few paragraphs below, it is referenced as "Identity Key" or simply "Identity", which is a bit misleading, as Credentials are supposed to contain an additional "identity" which is not the key. I propose we clear up the terminology a bit here and refer to the public key contained in a Credential as "Signature Key".

Discussion:
Provider (SP) as described in I-D.ietf-mls-architecture.  In particular, we assume the SP provides the following services: <del> A long-term identity key provider which allows clients to </del> <ins> A long-term signature key provider which allows clients to </ins> authenticate protocol messages in a group. A broadcast channel, for each group, which will relay a message to

A KeyPackage object specifies a ciphersuite that the client supports, as well as providing a public key that others can use for key <del> agreement.  The client's identity key can be updated throughout the </del> <ins> agreement.  The client's signature key can be updated throughout the </ins> lifetime of the group by sending a new KeyPackage with a new <del> identity; the new identity MUST be validated by the authentication service. </del> <ins> signature key; the new signature key MUST be validated by the authentication service. </ins> When used as InitKeys, KeyPackages are intended to be used only once and SHOULD NOT be reused except in case of last resort.  (See

The value for hpke_init_key MUST be a public key for the asymmetric encryption scheme defined by cipher_suite.  The whole structure is <del> signed using the client's identity key.  A KeyPackage object with an </del> <ins> signed using the client's signature key.  A KeyPackage object with an </ins> invalid signature field MUST be considered malformed.  The input to the signature computation comprises all of the fields except for the signature field.

creator, because they are derived from an authenticated key exchange protocol.  Subsequent leaf keys are known only by their owner. <del> Note that the long-term identity keys used by the protocol MUST be </del> <ins> Note that the long-term signature keys used by the protocol MUST be </ins> distributed by an "honest" authentication service for clients to authenticate their legitimate peers.

The second form considers authentication with respect to the sender, meaning the group members can verify that a message originated from a particular member of the group.  This property is provided by digital <del> signatures on the messages under identity keys. </del> <ins> signatures on the messages under signature keys. </ins> 14.3.
Change:
This PR adds clarification around X509 cert structure, the chain and its encoding X509.
NAME thanks for the suggestions. updated PR to reflect the changes . pls let me know ..
NAME i have pushed another commit .. can you please check. thanks

Discussion:
credential in a ratchet tree, the KeyPackage ciphersuite for a credential in a KeyPackage object. <ins> For X509Credential, each entry in the chain represents a single DER- encoded X509 certificate.  The chain is ordered such that the first entry (chain[0]) is the end-entity certificate and each subsequent certificate in the chain MUST be the issuer of the previous certificate.  The algorithm for the "public_key" in the end-entity certificate MUST match the relevant ciphersuite. </ins> For ciphersuites using Ed25519 or Ed448 signature schemes, the public key is in the format specified RFC8032.  For ciphersuites using ECDSA with the NIST curves P-256 or P-521, the public key is the output of
Change:
Thanks NAME pointing out the imprecision. Is this what you were looking for? Thanks NAME for the pointer to the correct registry.
This doesn't make sense because we don't actually use this registry. The signature scheme is defined by the ciphersuite, and the ciphersuite registry doesn't map to this unrelated registry
The is not authoritative in the group context and will always correspond with the one in the group (as is required by the generic description of the functionalities that Credentials have to provide). The SignatureScheme is there for when the Credential is handled in a context where there is no surrounding group. For example, when it's handled by the AS. There is a mapping from ciphersuit to SignatureScheme in Table 5, the entries of which correspond to the entries in the referenced registry. Is that what you meant?

Discussion:
The public key of a signature key pair matching the SignatureScheme specified by the CipherSuite of the group <del> The identity of the holder of the private keys </del> <ins> The identity of the holder of the private key </ins> Credentials MAY also include information that allows a relying party to verify the identity / signing key binding.
Change:
For the record: I asked NAME whether we could just update DeriveTreeSecret so that it always produces octets. But he pointed out that DeriveTreeSecret is also used to produce keys and nonces. Might be something to clean up later.

Discussion:
supported by all members. Initialize a one-member group with the following initial values <del> (where "0" represents an all-zero vector of size Hash.length): </del> <ins> (where "0" represents an all-zero vector of size KDF.Nh): </ins> Ratchet tree: A tree with a single node, a leaf containing an HPKE public key and credential for the creator
Change:
As briefly explained in the mailing list, commit messages currently contain encryptions for newly added group members that never even receive this commit message. This PR explicitely exlcudes them during the preparation of the UpdatePath.
I think this is a good point that wasn't really specified so far. The wording sounds a bit convoluted, maybe there is an easier way to describe it, like saying that the final resolution list should be filtered and all new leaf nodes should be removed from it.

Discussion:
from the closest node to the leaf to the root; each node MUST be the parent of its predecessor. <del> The number of ciphertexts in the "encrypted_path_secret" vector MUST be equal to the length of the resolution of the corresponding copath node.  Each ciphertext in the list is the encryption to the corresponding node in the resolution. </del> <ins> For each "UpdatePathNode", the resolution of the corresponding copath node MUST be filtered by removing all new leaf nodes added as part of this MLS Commit message.  The number of ciphertexts in the "encrypted_path_secret" vector MUST be equal to the length of the filtered resolution, with each ciphertext being the encryption to the respective resolution node. </ins> The HPKECiphertext values are computed as

the "path" field at its discretion. If populating the "path" field: Create a UpdatePath using the new <del> tree (which includes any new members).  The GroupContext for this operation uses the "group_id", "epoch", "tree_hash", and "confirmed_transcript_hash" values in the initial GroupContext object. </del> <ins> tree.  Any new member (from an add proposal) MUST be exluded from the resolution during the computation of the UpdatePath.  The GroupContext for this operation uses the "group_id", "epoch", "tree_hash", and "confirmed_transcript_hash" values in the initial GroupContext object. </ins> Assign this UpdatePath to the "path" field in the Commit.
Change:
As discussed on 2020-10-20, this field is not needed now that moved the signature under the confirmation tag.
We have a long-standing OPEN ISSUE on creating a group with a single Init message instead of N Add messages, which would change the work of initialization from O(N log N) to O(N). I would propose roughly the following: Then the processing would be: Find the welcome that's for you Initialize a one-member tree from the Welcome Use the UserInitKeys to populate the leaves of the tree Use the DirectPath to populate the creator's direct path (as in Update)
Fixed by URL
These keys are Client one-time use keys, so "UserInitKey" seems like a strange name.
I'm fine with ClientInitKey, as long as a client is not only a physical endpoint. Changes in the architecture doc should make this clear soon.

Discussion:
confirmation key and the "confirmed_transcript_hash" from the GroupInfo. <ins> Use the confirmed transcript hash and confirmation tag to compute the interim transcript hash in the new state. </ins> 11.3. By default, a GroupInfo message only provides the joiner with a
Change:
We have a changelog for the document by I-D release, but haven't been updating it as we go. This PR updates the changelog based on merged PRs and the few we expect to close before releasing draft-10. Marking this as draft right now, until the other PRs have merged.

Discussion:
draft-10 <ins> Allow new members to join via an external Commit (*) Enable proposals to be sent inline in a Commit (*) </ins> Re-enable constant-time Add (*) <ins> Change expiration extension to lifetime extension (*) Make the tree in the Welcome optional (*) PSK injection, re-init, sub-group branching (*) Require the initial init_secret to be a random value (*) Remove explicit sender data nonce (*) Do not encrypt to joiners in UpdatePath generation (*) Move MLSPlaintext signature under the confirmation tag (*) Explicitly authenticate group membership with MLSPLaintext (*) Clarify X509Credential structure (*) Remove uneeded interim transcript hash from GroupInfo (*) IANA considerations Derive an authentication secret Use Extract/Expand from HPKE KDF Clarify that application messages MUST be encrypted </ins> draft-09 Remove blanking of nodes on Add (*)
Change:
It looks like in Commit was moved to in UpdatePath, but some docs didn't get updated.

Discussion:
Welcome message at the same time, by taking the following steps: Construct an initial Commit object with the "proposals" field <del> populated from Proposals received during the current epoch, and empty "key_package" and "path" fields. </del> <ins> populated from Proposals received during the current epoch, and an empty "path" field. </ins> Generate a provisional GroupContext object by applying the proposals referenced in the initial Commit object, as described in

above), then it MUST be populated.  Otherwise, the sender MAY omit the "path" field at its discretion. <del> If populating the "path" field: Create a UpdatePath using the new </del> <ins> If populating the "path" field: Create an UpdatePath using the new </ins> tree.  Any new member (from an add proposal) MUST be exluded from the resolution during the computation of the UpdatePath.  The GroupContext for this operation uses the "group_id", "epoch", "tree_hash", and "confirmed_transcript_hash" values in the initial <del> GroupContext object. </del> <ins> GroupContext object.  The "leaf_key_package" for this UpdatePath must have a "parent_hash" extension. </ins> Assign this UpdatePath to the "path" field in the Commit.

Commit to the null optional.  Define "commit_secret" as the all- zero vector of the same length as a "path_secret" value would be. <del> Generate a new KeyPackage for the Committer's own leaf, with a "parent_hash" extension.  Store it in the ratchet tree and assign it to the "key_package" field in the Commit object. </del> If one or more PreSharedKey proposals are part of the commit, derive the "psk_secret" as specified in pre-shared-keys, where the order of PSKs in the derivation corresponds to the order of

ratchet tree and generate the "commit_secret": Apply the UpdatePath to the tree, as described in <del> synchronizing-views-of-the-tree, and store "key_package" at the Committer's leaf. </del> <ins> synchronizing-views-of-the-tree, and store "leaf_key_package" at the Committer's leaf. </ins> Verify that the KeyPackage has a "parent_hash" extension and that its value matches the new parent of the sender's leaf
Change:
This is a small suggestion to move the definition of the to the end of the first Extract-Expand (KDF) cycle of the [key schedule]. This makes more sense from a cryptographic perspective as we would not be using anything from the middle of a KDF cycle. A related suggestion is to remove the from the document. I removed it from the key schedule, removed all the mentions to forget it as soon as possible and updated the description of deriving the and from the [welcoming new members] section. [key schedule]: URL [welcoming new members]: URL
Thanks for the quick fix, NAME !

Discussion:
ratchet of node index N in some epoch n.  Then, for that member, at least the following values have been consumed and MUST be deleted: <del> the "commit_secret", "joiner_secret", "member_secret", "epoch_secret", "encryption_secret" of that epoch n as well as the "init_secret" of the previous epoch n-1, </del> <ins> the "commit_secret", "joiner_secret", "epoch_secret", "encryption_secret" of that epoch n as well as the "init_secret" of the previous epoch n-1, </ins> all node secrets in the Secret Tree on the path from the root to the leaf with node index N,

consume (at least) values G, F, D, AR0, AR1, K1, N1 as well as the key schedule secrets used to derive G (the "encryption_secret"), namely "init_secret" of epoch n-1 and "commit_secret", <del> "joiner_secret", "member_secret", "epoch_secret" of epoch n.  The client MAY retain (not consume) the values K0 and N0 to allow for out-of-order delivery, and SHOULD retain AR2 for processing future messages. </del> <ins> "joiner_secret", "epoch_secret" of epoch n.  The client MAY retain (not consume) the values K0 and N0 to allow for out-of-order delivery, and SHOULD retain AR2 for processing future messages. </ins> 8.6.

From the "joiner_secret" in the decrypted GroupSecrets object and the PSKs specified in the "GroupSecrets", derive the <del> "member_secret" and using that the "welcome_secret", "welcome_key", and "welcome_nonce".  Use the key and nonce to decrypt the "encrypted_group_info" field. </del> <ins> "welcome_secret" and using that the "welcome_key" and "welcome_nonce".  Use the key and nonce to decrypt the "encrypted_group_info" field. </ins> Verify the signature on the GroupInfo object.  The signature input comprises all of the fields in the GroupInfo object except the
Change:
use and instead of and , for consistency with the rest of the spec the key and nonce are now derived from the rather than randomly chosen

Discussion:
In order to allow the same Welcome message to be sent to all new members, information describing the group is encrypted with a <del> symmetric key and nonce randomly chosen by the sender.  This key and nonce are then encrypted to each new member using HPKE.  In the same encrypted package, the committer transmits the path secret for the lowest node contained in the direct paths of both the committer and the new member.  This allows the new member to compute private keys for nodes in its direct path that are being reset by the corresponding Commit. </del> <ins> symmetric key and nonce derived from the "joiner_secret" for the new epoch.  The "joiner_secret" is then encrypted to each new member using HPKE.  In the same encrypted package, the committer transmits the path secret for the lowest node contained in the direct paths of both the committer and the new member.  This allows the new member to compute private keys for nodes in its direct path that are being reset by the corresponding Commit. </ins> If the sender of the Welcome message wants the receiving member to include a PSK in the derivation of the "epoch_secret", they can