jiebi/TextFlow huggingface dataset:
Original text:
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>  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>  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>  Verify the signature on the GroupInfo object.  The signature input comprises all of the fields in the GroupInfo object except the

Reviewer comments:
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 !

Revised text:
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:  <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",  <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  <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
Original text:
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>  If the sender of the Welcome message wants the receiving member to include a PSK in the derivation of the "epoch_secret", they can

Reviewer comments:
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

Revised text:
In order to allow the same Welcome message to be sent to all new members, information describing the group is encrypted with a  <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
Original text:
that the chosen version and ciphersuite is the best option supported by all members. <del> Initialize a one-member group with the following initial values (where "0" represents an all-zero vector of size KDF.Nh): </del>  Ratchet tree: A tree with a single node, a leaf containing an HPKE public key and credential for the creator Tree hash: The root hash of the above ratchet tree <del> Confirmed transcript hash: 0 </del>  <del> Interim transcript hash: 0 </del>  Init secret: a fresh random value of size "KDF.Nh"

Reviewer comments:
While reviewing , I noticed that in one place, we define the initial to be the all-zero vector, and in another, we define it to be the empty octet string. In keeping with the idea of starting chained hashes with the empty octet string, this PR normalizes on the empty octet string for the transcript hashes as well.

Revised text:
that the chosen version and ciphersuite is the best option supported by all members.  <ins> Initialize a one-member group with the following initial values: </ins> Ratchet tree: A tree with a single node, a leaf containing an HPKE public key and credential for the creator Tree hash: The root hash of the above ratchet tree  <ins> Confirmed transcript hash: the zero-length octet string </ins>  <ins> Interim transcript hash: the zero-length octet string </ins> Init secret: a fresh random value of size "KDF.Nh"
Original text:
RFC EDITOR PLEASE DELETE THIS SECTION.  draft-10 Allow new members to join via an external Commit (*)

Reviewer comments:
Immediately after I published draft-11, NAME noticed that I had failed to update the change log. This PR adds it to the editor's copy, so that it will be included in future versions.

Revised text:
RFC EDITOR PLEASE DELETE THIS SECTION. <ins> draft-11 Include subtree keys in parent hash (*) Pin HPKE to draft-07 (*) Move joiner secret to the end of the first key schedule epoch (*) Add an AppAck proposal Make initializations of transcript hashes consistent </ins> draft-10 Allow new members to join via an external Commit (*)
Original text:
The second form of authentication is that group members can verify a message originated from a particular member of the group.  This is guaranteed by a digital signature on each message from the sender's <del> identity key. </del>  15.3.

Reviewer comments:
I think this word was left from previous changes to the name of this particular key.. cc./ NAME NAME
Thanks Sofía !

Revised text:
The second form of authentication is that group members can verify a message originated from a particular member of the group.  This is guaranteed by a digital signature on each message from the sender's  <ins> signature key. </ins> 15.3.
Original text:
has received its Commit message back from the server does it update its state to reflect the new member's addition. <del> Upon receiving the Welcome message and the corresponding Commit, the new member will be able to read and send new messages to the group. Messages received before the client has joined the group are ignored. </del>  Subsequent additions of group members proceed in the same way.  Any member of the group can download a KeyPackage for a new client and broadcast an Add message that the current group can use to update their state, and a Welcome message that the new client can use to <del> initialize its state. </del>  To enforce the forward secrecy and post-compromise security of messages, each member periodically updates their leaf secret.  Any

Reviewer comments:
(see issue for details).
Currently section "4. Protocol Overview" states: I think this is a legacy from before the propose/commit scheme and got carried over. New members no longer need the Commit. The subsequent diagram also needs to be adapted.

Revised text:
has received its Commit message back from the server does it update its state to reflect the new member's addition.  <ins> Upon receiving the Welcome message, the new member will be able to read and send new messages to the group.  Messages received before the client has joined the group are ignored. </ins> Subsequent additions of group members proceed in the same way.  Any member of the group can download a KeyPackage for a new client and broadcast an Add message that the current group can use to update their state, and a Welcome message that the new client can use to  <ins> initialize its state and join the group. </ins> To enforce the forward secrecy and post-compromise security of messages, each member periodically updates their leaf secret.  Any
Original text:
managed in GitHub, but any substantive change should be discussed on the MLS mailing list. <del> Groups of agents who want to send each other encrypted messages need a way to derive shared symmetric encryption keys.  For two parties, this problem has been studied thoroughly, with the Double Ratchet emerging as a common solution doubleratchet signal.  Channels </del>  implementing the Double Ratchet enjoy fine-grained forward secrecy as well as post-compromise security, but are nonetheless efficient enough for heavy use over low-bandwidth networks. <del> For groups of size greater than two, a common strategy is to </del>  unilaterally broadcast symmetric "sender" keys over existing shared symmetric channels, and then for each agent to send messages to the group encrypted with their own sender key.  Unfortunately, while this

Reviewer comments:
It first reads as if MLS allows groups to communicate with each other, which I don't think is the intent.
Thanks Mark ;)

Revised text:
managed in GitHub, but any substantive change should be discussed on the MLS mailing list.  <ins> A group of agents who want to send each other encrypted messages needs a way to derive shared symmetric encryption keys.  For two parties, this problem has been studied thoroughly, with the Double Ratchet emerging as a common solution doubleratchet signal.  Channels </ins> implementing the Double Ratchet enjoy fine-grained forward secrecy as well as post-compromise security, but are nonetheless efficient enough for heavy use over low-bandwidth networks.  <ins> For a group of size greater than two, a common strategy is to </ins> unilaterally broadcast symmetric "sender" keys over existing shared symmetric channels, and then for each agent to send messages to the group encrypted with their own sender key.  Unfortunately, while this
Original text:
If R is blank, replace R with its left child until R is either non-blank or a leaf node <del> If R is a leaf node, the check fails </del>  If R.parent_hash is equal to the Parent Hash of P with Co-Path Child L, the check passes

Reviewer comments:
Add a missing word. Fail on blank leaf.
The is currently not very well described. Depending on the reading it might also be wrong. In particular, the condition , if implemented as described makes it so that valid parent hashes are rejected. Take for example a simple tree with two leafs where the right leaf (node 2) sends a commit. In this case the other leaf will reject the parent hash because it fails when going down to the right leaf. This might be a wrong interpretation of the described verification procedure but then the description needs updating. I suggest to add a more formal description of the parent hash generation and verification (e.g. pseudocode) to reduce ambiguity.
I think that condition should read "If R is a blank leaf node, the check fails".
Agree with NAME here; the matches this interpretation. So I think we just need to adjust that text.
I agree, this was fixed in

Revised text:
If R is blank, replace R with its left child until R is either non-blank or a leaf node  <ins> If R is a blank leaf node, the check fails </ins> If R.parent_hash is equal to the Parent Hash of P with Co-Path Child L, the check passes
Original text:
Blank the intermediate nodes along the path from the removed leaf to the root  11.1.4. A PreSharedKey proposal can be used to request that a pre-shared key

Reviewer comments:
This PR adds text to truncate the tree to perform garbage collection on removal. [ref: URL]
Over time we lost the rule that the ratchet tree should also be trimmed after members have been removed (where it really makes sense), not only when members are added.
NAME posted to address this issue
Fixed in - URL
Earlier, we had considered a "masking" approach for sender data, much like QUIC does for . This approach would save 28 bytes of overhead (nonce + tag), but was abandoned because of uncertainty around the security of the masking approach. Since then, Bellare et al. published , which includes what is effectively a proof of the security properties of the QUIC scheme. The QUIC scheme is essentially scheme HN1 of the paper, the main difference being that QUIC encrypt not the nonce directly, but a packet number which is used to compute the nonce. Our application would be similar, since we would encrypt metadata used to encrypt the key and the nonce. Given this new analysis, is it time to bring back masking?
Fixed by

Revised text:
Blank the intermediate nodes along the path from the removed leaf to the root <ins> Truncate the tree by reducing the size of tree until the rightmost non-blank leaf node </ins> 11.1.4. A PreSharedKey proposal can be used to request that a pre-shared key
Original text:
a Commit message, who apply it to keep their local views of the tree in sync with the sender's.  More specifically, when a member commits a change to the tree (e.g., to add or remove a member), it transmits <del> an UpdatePath message containing a set of public and encrypted private values for intermediate nodes in the direct path of a leaf. The other members of the group use these values to update their view of the tree, aligning their copy of the tree to the sender's. </del>  <del> To transmit this update, the sender broadcasts to the group the following information for each node in the direct path of the leaf, including the root: </del>  The public key for the node The path secret value for a given node is encrypted for the subtree corresponding to the parent's non-updated child, that is, the child <del> on the copath of the leaf node.  There is one encrypted path secret for each public key in the resolution of the non-updated child. </del>  <del> The recipient of a path update processes it with the following steps: </del>  Compute the updated path secrets.

Reviewer comments:
202105 Interim: To be reviewed by editors.
Ready to merge modulo one nit.

Revised text:
a Commit message, who apply it to keep their local views of the tree in sync with the sender's.  More specifically, when a member commits a change to the tree (e.g., to add or remove a member), it transmits  <ins> an UpdatePath containing a set of public keys and encrypted path secrets for intermediate nodes in the direct path of its leaf.  The other members of the group use these values to update their view of the tree, aligning their copy of the tree to the sender's. </ins>  <ins> An UpdatePath contains the following information for each node in the direct path of the sender's leaf, including the root: </ins> The public key for the node The path secret value for a given node is encrypted for the subtree corresponding to the parent's non-updated child, that is, the child  <ins> on the copath of the sender's leaf node.  There is one encryption of the path secret to each public key in the resolution of the non- updated child. </ins>  <ins> The recipient of an UpdatePath processes it with the following steps: </ins> Compute the updated path secrets.
Original text:
the uncompressed Elliptic-Curve-Point-to-Octet-String conversion according to SECG.  Note that each new credential that has not already been validated by the application MUST be validated against the Authentication Service.

Reviewer comments:
The spec doesn't say anything about the signature encoding yet. This PR adds a paragraph clarifying that signature encoding is done like in TLS.

Revised text:
the uncompressed Elliptic-Curve-Point-to-Octet-String conversion according to SECG. <ins> The signatures used throughout this document are encoded as specified in RFC8446.  In particular, ECDSA signatures are DER-encoded and EdDSA signatures are defined as the concatenation of "r" and "s" as specified in RFC8032. </ins> Note that each new credential that has not already been validated by the application MUST be validated against the Authentication Service.
Original text:
Note that, as a PSK may have a different lifetime than an update, it does not necessarily provide the same Forward Secrecy (FS) or Post- <del> Compromise Security (PCS) guarantees as a Commit message. </del>  Each PSK in MLS has a type that designates how it was provisioned. External PSKs are provided by the application, while recovery and re-

Reviewer comments:
Most of these were stale; see comments for more specifics. I opened as a general issue arising from the final TODO.
Discussed at 20211004 interim, will merge after adding text in comment. NAME create new issue for multiple PSKs and PR for cascading HKDF.
The "Sequencing of State Changes" and "Application Messages" sections date to very early in the document's life, and probably need some updates to reflect current thinking.
Closing for now, might reopen based on WGLC review.

Revised text:
Note that, as a PSK may have a different lifetime than an update, it does not necessarily provide the same Forward Secrecy (FS) or Post-  <ins> Compromise Security (PCS) guarantees as a Commit message.  Unlike the key pairs populated in the tree by an Update or Commit, which always freshly generated, PSKs may be pre-distributed and stored.  This creates the risk that a PSK may be compromised in the process of distribution and storage.  The security that the group gets from injecting a PSK thus depends on both the entropy of the PSK and the risk of compromise.  These factors are outside of the scope of this document, but should be considered by application designers relying on PSKs. </ins> Each PSK in MLS has a type that designates how it was provisioned. External PSKs are provided by the application, while recovery and re-
Original text:
in the Handshake Key Schedule to be ease chaining in case we switch design. (*)  draft-00 Initial adoption of draft-barnes-mls-protocol-01 as a WG item.

Reviewer comments:
The math for left-balanced binary trees is very reliable once you have it right, but can be hard to get right from scratch. This PR provides an appendix that explains a theory and code for managing these trees.
I feel this is very useful to have in the draft for implementors. What should be the plan to merge it ? NAME
Thanks ! I expect that it's going to be very useful for implementers. I am trusting that it is correct Python syntax ;) Pointed out a potential typo in the comments.

Revised text:
in the Handshake Key Schedule to be ease chaining in case we switch design. (*) <ins> Added an appendix with example code for tree math </ins> draft-00 Initial adoption of draft-barnes-mls-protocol-01 as a WG item.
Original text:
A signature algorithm <del> MLS uses draft-08 of HPKE I-D.irtf-cfrg-hpke for public-key encryption.  The "DeriveKeyPair" function associated to the KEM for the ciphersuite maps octet strings to HPKE key pairs. </del>  Ciphersuites are represented with the CipherSuite type.  HPKE public keys are opaque values in a format defined by the underlying protocol

Reviewer comments:
HPKE is in the RFC Editor queue, so there shouldn't be any further changes.
MLS draft-12 still references draft-08 of HPKE, which is now on draft-12. We should update to the final version of HPKE before finalizing MLS.

Revised text:
A signature algorithm  <ins> MLS uses HPKE for public-key encryption I-D.irtf-cfrg-hpke.  The "DeriveKeyPair" function associated to the KEM for the ciphersuite maps octet strings to HPKE key pairs. </ins> Ciphersuites are represented with the CipherSuite type.  HPKE public keys are opaque values in a format defined by the underlying protocol
Original text:
as follows I-D.irtf-cfrg-hpke RFC8446: The hash used for the MLS transcript hash is the one referenced in <del> the ciphersuite name.  In the ciphersuites defined above, "SHA256" and "SHA512" refer to the SHA-256 and SHA-512 functions defined in SHS. </del>  It is advisable to keep the number of ciphersuites low to increase the chances clients can interoperate in a federated environment, <del> therefore the ciphersuites only inlcude modern, yet well-established </del>  algorithms.  Depending on their requirements, clients can choose between two security levels (roughly 128-bit and 256-bit).  Within the security levels clients can choose between faster X25519/X448

Reviewer comments:
I suggest that we consider including a ciphersuite that enables AES256 GCM with SHA384 and that for signatures ECDSA with P-384 (and SHA-384) is also permitted. The NSA restricts commercial applications to certain algorithms for applications that are used in or in coordination with the U.S. federal government and, from a general availability perspective, adding this could expand protocol use potential.
I presume you're thinking of here? I realize that the table specifies P-384 and SHA-384; is it your understanding that it forbids using bigger curves/hashes?
Both Suite B and alignment to the . The other options currently in the spec, size accounted for, do not align to requirements.
You didn't answer my question about forbidding the use of bigger curves/hashes. Would the cases you're interested in be covered by the AES-256 / SHA-512 / P-521 suite?
If this is needed for the reasons mentioned in the issue, I have no objections.

Revised text:
as follows I-D.irtf-cfrg-hpke RFC8446: The hash used for the MLS transcript hash is the one referenced in  <ins> the ciphersuite name.  In the ciphersuites defined above, "SHA256", "SHA384", and "SHA512" refer to the SHA-256, SHA-384, 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,  <ins> therefore the ciphersuites only include modern, yet well-established </ins> algorithms.  Depending on their requirements, clients can choose between two security levels (roughly 128-bit and 256-bit).  Within the security levels clients can choose between faster X25519/X448
Original text:
those in the GroupInfo object, according to the definitions of those extensions.  Note that the latter two requirements mean that all MLS extensions are mandatory, in the sense that an extension in use by the group MUST be supported by all members of the group.

Reviewer comments:
A GroupInfo (or a PublicGroupState) should only ever contain one RatchetTreeExtension. Either that or it should be specified what happens if there is more than one.
Seems like we should be able to make a general proclamation that extension IDs MUST be unique in a given vector of extensions, whether that's GroupContext, KeyPackage, GroupInfo, GroupContextExtensions, etc.
Sounds good to me. I'll draft a PR.
SGTM, one minor rephrasing for more clarity.

Revised text:
those in the GroupInfo object, according to the definitions of those extensions. <ins> Any field containing a list of extensions MUST NOT have more than one extension of any given type. </ins> Note that the latter two requirements mean that all MLS extensions are mandatory, in the sense that an extension in use by the group MUST be supported by all members of the group.