11. <del> The primary purpose of the handshake protocol is to provide an </del>  authenticated group key exchange to clients.  In order to protect <del> Application messages sent among those members of a group, the Application secret provided by the handshake key schedule is used to derive encryption keys for the Message Protection Layer. </del>  Application messages MUST be protected with the Authenticated- Encryption with Associated-Data (AEAD) encryption scheme associated messages MUST use asymmetric signatures to strongly authenticate the sender of a message. <del> Each member maintains their own chain of Application secrets, where the first one is derived based on a secret chained from the Epoch secret.  As shown in key-schedule, the initial Application secret is bound to the identity of each client to avoid collisions and allow support for decryption of reordered messages. Subsequent Application secrets MUST be rotated for each message sent in order to provide stronger cryptographic security guarantees.  The Application Key Schedule use this rotation to generate fresh AEAD encryption keys and nonces used to encrypt and decrypt future Application messages.  In all cases, a participant MUST NOT encrypt more than expected by the security bounds of the AEAD scheme used. Note that each change to the Group through a handshake message will cause a change of the group Secret.  Hence this change MUST be applied before encrypting any new Application message.  This is required for confidentiality reasons in order for members to avoid receiving messages from the group after leaving, being added to, or excluded from the group. </del> 11.1.  The group members MUST use the AEAD algorithm associated with the negotiated MLS ciphersuite to AEAD encrypt and decrypt their Application messages according to the Message Framing section. The group identifier and epoch allow a recipient to know which group secrets should be used and from which Epoch secret to start computing <del> other secrets and keys.  The "sender" identifier is used to derive the member's Application secret chain from the initial group Application secret.  The application generation field is used to determine which Application secret should be used from the chain to compute the correct AEAD keys before performing decryption. </del>  Application messages SHOULD be padded to provide some resistance against traffic analysis techniques over encrypted traffic.  CLINIC length of the plaintext by allowing to send a variable number of ciphertext blocks ? ]] <del> 11.2. </del>  Since each Application message contains the group identifier, the epoch and a message counter, a client can receive messages out of

Basic idea: Application Key Schedule consists of a left balanced binary tree of secrets (the "AS Tree") and one symmetric ratchet per group member. The AS Tree has the same node/edge structure as the ratchet tree for that epoch. Members are assigned the same leaves.Each node in the AS Tree is assigned a secret. The root's secret = applicationsecret. The secrets of children are derived from that of their parent.The secret of a leaf is the initial secret of a symmetric hash ratchet. The ratchet generates the key/nonce sequence used by the leaf's group member to encrypt messages during that epoch. Other comments: I included a "Deletion Schedule": keys, nonces are 'consumed' if they are used to encrypt or successfully decrypt a message. secrets are 'consumed' if value derived from it is consumed. Any consumed value must be immediately deleted for reasons of forward secrecy.I was very generous with contexts for all calls to HKDF. E.g. I included Hash(GroupState[n]) in the context of every call to HKDF. True, I dont think its neccesary to prove security against more coarse adversarial models (e.g. that only do all-or-nothing state leakage). Still, as a matter of the "defense in depth" principle I think including as much relevant context as possible during all key/secret derivation is a good idea. Albeit only as long as the price (in computation, complexity, etc) is not to high. To that end, I purposefully use Hash(GroupState_[n]) in the context as it is short, needs only to be computed once at the start of the epoch and can then be used to very cheaply to construct all contexts needed for the rest of the new application key schedule.Disclaimer: I'm a bit of a noob when it comes to Markdown, RFCs and github so forgive me (and tell me!) if I've done something wrong here. Co-contributors: Benjamin Beurbouche, Sandro Coretti, Yevgeniy Dodis,
Merging this despite outstanding comments. NAME and I will handle our requested edits in a couple of follow-up PRs.
Here's the Weekly Digest for : This week, 8 issues were created. Of these, 4 issues have been closed and 4 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :heart: , by The issue most discussed this week has been: :speaker: , by It received 9 comments. This week, no pull requests has been proposed by the users. This week, 4 users have contributed to this repository. They are , , , and . This week, no user has starred this repository. This week, there have been 4 commits in the repository. These are: :hammerandwrench: Merge pull request from rozbb/mlsplaintext-signature Multiple clarifications around Framing by :hammerandwrench: Merge pull request from rozbb/hpke-encrypt Clarify how HPKE ciphertexts are computed by :hammerandwrench: by :hammerand_wrench: by # RELEASES This week, no releases were published. That's all for this week, please watch :eyes: and star :star: to receive next weekly updates. :smiley:
Here's the Weekly Digest for : - - Last week 4 issues were created. Of these, 1 issues have been closed and 3 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :speaker: , by It received 4 comments. - - Last week, 9 pull requests were created, updated or merged. Last week, 8 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 1 pull request was merged. :purpleheart: , by - - Last week there were 4 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
We should ensure that there is adequate anti-replay protection for both Handshake and Application messages. (In particular, we should define what anti-replay issues are a concern.) Could be related to if we want to solve it at that framing layer.
It looks like application key schedule on its own may not be enough to prevent replay attacks if out-of-order messages are supported (and it seems like they are supported according to section 9.2.1). Lets say we are at epoch x, and the receiver derives applicationsecret[sender][0] for epoch x. Then, the receiver receives message1 (generation = 1) first before message0. In order to decrypt message1, the receiver needs to advance the application secret forward once to applicationsecret[sender][1] to get message1 nonce and AEAD secret. The receiver then happily processes message 1. However, the receiver cannot forget applicationsecret[sender][0] at this time; otherwise it will never be able to decrypt message0 so it has to keep applicationsecret[sender][0] around. If the receiver receives message1 again, it can compute applicationsecret[sender][1] from applicationsecret[sender][0] and process the message. Hence, it seems that key schedule on its own will not prevent replay attacks. The receiver needs to remember that it has already processed message1. The same problem may apply to receiving a message from epoch N+1 while not all messages from epoch N have been received (if such case is possible). Replay attack counter-measures may be implemented as part of key schedule logic or separately, but it looks like implementors need to pay attention to this.
Obviously, if you keep a previous application secret, you are breaking FS. This is forbidden by the protocol. The protocol mandates: "Receivers MUST delete an Application Secret once it has been used to derive the corresponding AEAD key and nonce as well as the next Application Secret. Receivers MAY keep the AEAD key and nonce around for some reasonable period."
Cf. "Updating the Application Secret"
Does it mean that receiving out-of-order messages is not possible? If I abandon applicationsecret[sender][0] and advance to applicationsecret[sender][2] after receiving message 1 before message 0, I will never be able to process message 0. Is this intended behavior or am I missing something?
No, you can do out of order, but what you keep are the AEAD keys/nonces and not the Application Secrets. The idea is the following: 1 - Compute Application Secret[sender][0] 2 - Derive AEAD Key[Sender][0] and AEAD Nonce[Sender][0] from Application Secret[sender][0] 3 - Overwrite Application Secret[sender][0] with Application Secret[sender][1] Basically, you should see these 3 steps as a single operation Now, if you iterate over that you can get more AEAD Keys and nonces [0 ... N] to receive out of order. Because of step 3 you have local Forward Secrecy. Note that you never store more than a single (the latest) Application Secret per sender and that you have the keys [0...N] to decrypt out of order.
Makes sense. Thanks for explaining. I suspect receiving out of order messages from a different epoch works in a similar way. If I am at epoch 0, and I receive a message from epoch 2, I derive and keep applicationsecret for epoch 1 and roll the initsecret forward. From the implementation perspective, how do I know when I can safely discard an application secret for a particular epoch? Or how do I know that no more messages are coming for a particular sender/epoch? Do you think there is value in adding a paragraph clarifying how the key schedule ensures replay attack protection to the spec? I know these are probably all implementation questions, but I suspect these may be the questions the implementors may be asking.
NAME I have some text stashed for when to discard the previous application secrets after there is a new epoch, so I will handle that. The idea is that you "publish" the number of application messages you sent in the previous epoch, but that is to be discussed... Regarding replay, if you asked, it means clarification might be helpful here, do you want to submit a PR and assign me for review ? Otherwise just tell me and I'll handle it... : )
NAME I think you should review the below and update the spec as you see fit : ) -- I would update section 9.2.1 with something like: If receiver's application secret is at generation N, and the receiver receives an out of order message with generation N+x (where x>0), the receiver MUST advance the application secret forward to application secret N+x+1 after processing the out of order message. For every message with generation between N and N+x-1 (messages that have not been received), the receiver SHOULD derive AEAD nonce and AEAD key and store them in order to be able to decrypt these messages later. Application secret MUST NOT be kept at generation N in order allow for decryption of out-of-order messages. Instead, stored AEAD key and nonce will allow for decryption of out-of-order messages when received later. -- We may also introduce a short new section "Message Replay Protection" with something like: Application key schedule provides replay attack counter-measures. If a message is replayed, the receiver should not have the right AEAD key nor have the application secret that could be used for deriving the right AEAD key for the replayed message. Hence, replayed message will be rejected by the receiver.
I think this is adequately addressed by and

11.  <ins> The primary purpose of the Handshake protocol is to provide an </ins> authenticated group key exchange to clients.  In order to protect  <ins> Application messages sent among the members of a group, the Application secret provided by the Handshake key schedule is used to derive nonces and encryption keys for the Message Protection Layer according to the Application Key Schedule.  That is, each epoch is equipped with a fresh Application Key Schedule which consist of a tree of Application Secrets as well as one symmetric ratchet per group member. Each client maintains their own local copy of (parts of) the Application Key Schedule for each epoch during which they are a group member.  They derive new keys, nonces and secrets as needed while deleting old ones as soon as they have been used. </ins> Application messages MUST be protected with the Authenticated- Encryption with Associated-Data (AEAD) encryption scheme associated messages MUST use asymmetric signatures to strongly authenticate the sender of a message.  11.1. <ins> The Application schedule begins with the Application secrets which are arranged in an "Application Secret Tree" or AS Tree for short; a left balanced binary tree with the same set of nodes and edges as the epoch's ratchet tree.  Each leaf in the AS Tree is associated with the same group member as the corresponding leaf in the ratchet tree. Nodes are also assigned an index according to their position in the array representation of the tree (described in tree-math).  If V is a node in the AS Tree then IndexOf(V) denotes it's index while V.leftChild and V.rightChild denote the children of V (if they exist). Each node in the tree is assigned a secret.  The root's secret is simply the application_secret of that epoch.  (See key-schedule for the definition of application_secret.) The secret of any other node in the tree is derived from its parent's secret using a call to Derive-Secret.  The context for the call is the (hash of the) Group state of the epoch and the index of the node whose secret is being derived. If V is a node in the ASTree then ASTreeContext[V] denotes an ASTreeContext variable with: gshash = Hash(GroupState_[n]) node_index = IndexOf(V) Moreover, the secrets of the children of V are defined to be: Note that fixing concrete values for GroupState_[n] and application_secret completely defines all secrets in the AS Tree. 11.2. The secret of a leaf in the AS Tree is used to initiate a symmetric hash ratchet which generates a sequence of keys and nonces.  The group member assigned to that leaf uses the j-th key/nonce pair in the sequence to encrypt (using the AEAD) the j-th message they send during that epoch.  In particular, each key/nonce pair MUST NOT be used to encrypt more than one message. More precisely, the initial secret of the ratchet for the group member assigned to the leaf with index i is simply the secret of that leaf. Keys, nonces and secrets of ratchets are derived using HKDF-Expand- Label.  The context in a given call consists of (a hash of) the current Group state, the index of the sender's leaf in the ratchet tree and the position in the ratchet.  In particular, the index of the sender's leaf in the ratchet tree is the same as the index of the leaf in the AS Tree used to initialize the sender's ratchet. Ratchet_position is initialized to 1 for the first HKDF-Expand-Label call of a new ratchet and incremented for each subsequent call in that ratchet. HashRatCont[i, j] denotes a RatchetContext variable where: gshash = Hash(GropuState_[n]) leaf_index = i ratchet_position = j Using this notation the ratchet for the group member at leaf i is defined to be: Here, AEAD.nonceLen and AEAD.keyLength denote the lengths in bytes of the nonce and key for the AEAD scheme defined by the ciphersuite. 11.3. It is important to delete all security sensitive values as soon as they, or another value derived from them, is used for encryption or decryption. More precisely, the values application_[i]_[j]_key and application_[i]_[j]_nonce are said to be "consumed" if they were used either to: encrypt or (successfully) decrypt a message or if a key, nonce or secret derived from S has been consumed.  (This goes both for values derived via Derive-Secret and HKDF-Expand- Label). Here, S may be the init_secret, update_secret, epoch_secret, application_secret as well as any secret in the AS Tree or one of the ratchets. As soon as a group member consumes a value they MUST immediately delete (all representations of) that value.  This is crucial to ensuring Forward Secrecy for past messages.  Members MAY keep unconsumed values around for some reasonable amount of time even if their generating secret was already consumed (e.g. due to out of order message delivery). For example, suppose a group member encrypts or (successfully) decrypts a message using the j-th key and nonce in the i-th ratchet. Then, for that member, at least the following values have been consumed and MUST be deleted: the init_secret, update_secret, epoch_secret, application_secret of that epoch, all node secrets in the AS Tree on the path from the root to the leaf with index i, the first j secrets in the i-th ratchet and application_[i]_[j]_key and application_[i]_[j]_nonce. Concretely, suppose we have the following AS Tree. Then if a client uses key KD1 and nonce ND1 during epoch n then it must consume (at least) values G, F, D0, D1, KD1, ND1 as well as the update_secret and init_secret used to derive G (i.e. the application_secret). 11.4. During each epoch senders MUST NOT encrypt more messages than permitted by the security bounds of the AEAD scheme used. Note that each change to the Group through a Handshake message will also set a new application_secret.  Hence this change MUST be applied before encrypting any new Application message.  This is required both to ensure that any users removed from the group can no longer receive messages and to (potentially) recover confidentiality and authenticity for future messages despite a past state compromise. [[ OPEN ISSUE: At the moment there is no contributivity of Application secrets chained from the initial one to the next generation of Epoch secret.  While this seems safe because cryptographic operations using the application secrets can't affect the group init_secret, it remains to be proven correct. ]] 11.5. </ins> The group members MUST use the AEAD algorithm associated with the negotiated MLS ciphersuite to AEAD encrypt and decrypt their Application messages according to the Message Framing section. The group identifier and epoch allow a recipient to know which group secrets should be used and from which Epoch secret to start computing  <ins> other secrets and keys.  The sender identifier is used to identify the member's symmetric ratchet from the initial group Application secret.  The application generation field is used to determine how far into the ratchet to iterate in order to reproduce the required AEAD keys and nonce for performing decryption. </ins> Application messages SHOULD be padded to provide some resistance against traffic analysis techniques over encrypted traffic.  CLINIC length of the plaintext by allowing to send a variable number of ciphertext blocks ? ]]  <ins> 11.6. </ins> Since each Application message contains the group identifier, the epoch and a message counter, a client can receive messages out of


transcript of group operations, using the transcript hash from the provisional GroupState object: <del> [[ OPEN ISSUE: The confirmation data and signature data should probably cover the same data as the one we cover with the GroupState. ]] </del> HMAC RFC2104 uses the Hash algorithm for the ciphersuite in use. Sign uses the signature algorithm indicated by the signer's credential in the roster. <del> [[ OPEN ISSUE: The Add and Remove operations create a "double-join" situation, where a member's leaf key is also known to another client. When a member A is double-joined to another B, deleting A will not remove them from the conversation, since they will still hold the leaf key for B.  These situations are resolved by updates, but since operations are asynchronous and members may be offline for a long time, the group will need to be able to maintain security in the presence of double-joins. ]] </del> [[ OPEN ISSUE: It is not possible for the recipient of an handshake message to verify that ratchet tree information in the message is accurate, because each node can only compute the secret and private Application secret is used to bind the Application messages with the next key and add some freshness. <del> [[OPEN ISSUE: The HKDF context field is left empty for now.  A proper security study is needed to make sure that we do not need more </del>  information in the context to achieve the security goals.]] [[ OPEN ISSUE: At the moment there is no contributivity of

Clean up some OPEN ISSUES that aren't open any more Make the welcome/add diagram clearer
Here's the Weekly Digest for : - - Last week 4 issues were created. Of these, 1 issues have been closed and 3 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :speaker: , by It received 4 comments. - - Last week, 9 pull requests were created, updated or merged. Last week, 8 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 1 pull request was merged. :purpleheart: , by - - Last week there were 4 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

transcript of group operations, using the transcript hash from the provisional GroupState object:  HMAC RFC2104 uses the Hash algorithm for the ciphersuite in use. Sign uses the signature algorithm indicated by the signer's credential in the roster.  [[ OPEN ISSUE: It is not possible for the recipient of an handshake message to verify that ratchet tree information in the message is accurate, because each node can only compute the secret and private Application secret is used to bind the Application messages with the next key and add some freshness.  <ins> [[ OPEN ISSUE: The HKDF context field is left empty for now.  A proper security study is needed to make sure that we do not need more </ins> information in the context to achieve the security goals.]] [[ OPEN ISSUE: At the moment there is no contributivity of


draft-06  Rename the GroupState structure to GroupContext (*) draft-05 The sender of a Remove message generates it as as follows:  Generate a fresh leaf key pair Compute its direct path in the current ratchet tree, starting from <del> the removed leaf </del>  A member receiving a Remove message first verifies the signature on the message.  The member then updates its state as follows: <del> Update the ratchet tree by replacing nodes in the direct path from the removed leaf using the information in the Remove message </del> Update the ratchet tree by setting to blank all nodes in the direct path of the removed leaf, and also setting the root node to blank Truncate the tree such that the rightmost non-blank leaf is the last node of the tree <del> Note that, in step 4, there must be at least one non-null element in the tree, since any valid GroupContext must have the current member in the tree and self-removal is prohibited.  The same reasoning justifies the existence of a non-blank leaf in the ratchet tree in step 5. </del>  The "update_secret" resulting from this change is the "path_secret[i+1]" derived from the "path_secret[i]" associated to

Here's the Weekly Digest for : - - Last week 5 issues were created. Of these, 1 issues have been closed and 4 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by - - Last week, 9 pull requests were created, updated or merged. Last week, 3 pull requests were opened. :greenheart: , by :greenheart: , by :greenheart: , by Last week, 1 pull request was updated. :yellowheart: , by Last week, 5 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 8 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

draft-06 <ins> Reorder blanking and update in the Remove operation (*) </ins> Rename the GroupState structure to GroupContext (*) draft-05 The sender of a Remove message generates it as as follows: <ins> Blank the path from the removed leaf to the root node for the time of the computation Truncate the tree such that the rightmost non-blank leaf is the last node of the tree, for the time of the computation </ins> Generate a fresh leaf key pair Compute its direct path in the current ratchet tree, starting from  <ins> the sender's leaf </ins> A member receiving a Remove message first verifies the signature on the message.  The member then updates its state as follows:  Update the ratchet tree by setting to blank all nodes in the direct path of the removed leaf, and also setting the root node to blank Truncate the tree such that the rightmost non-blank leaf is the last node of the tree  <ins> Update the ratchet tree by replacing nodes in the direct path from the sender's leaf using the information in the Remove message Note that there must be at least one non-null element in the tree, since any valid GroupContext must have the current member in the tree and self-removal is prohibited </ins> The "update_secret" resulting from this change is the "path_secret[i+1]" derived from the "path_secret[i]" associated to


corresponding to the ciphersuite in use, as well as the credential under which the UserInitKey was signed <del> The update secret resulting from this change is an all-zero octet </del>  string of length Hash.length. After processing an Add message, the new member SHOULD send an Update path from the updated leaf using the information contained in the Update message <del> The update secret resulting from this change is the path secret for the root node of the ratchet tree. </del>  9.4. justifies the existence of a non-blank leaf in the ratchet tree in step 5. <del> The update secret resulting from this change is the path secret computed for the root node of the ratchet tree in the first step. </del>  10.

"The update secret resulting from this change is the path secret for the root node of the ratchet tree." is suspicious because in the derivation, the index for both the and is the same as the level of the node. It should be the "above the root" and not "for the root" (which is the one used to derive the of the root)...
Here's the Weekly Digest for : - - Last week 5 issues were created. Of these, 1 issues have been closed and 4 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by - - Last week, 9 pull requests were created, updated or merged. Last week, 3 pull requests were opened. :greenheart: , by :greenheart: , by :greenheart: , by Last week, 1 pull request was updated. :yellowheart: , by Last week, 5 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 8 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

corresponding to the ciphersuite in use, as well as the credential under which the UserInitKey was signed  <ins> The "update_secret" resulting from this change is an all-zero octet </ins> string of length Hash.length. After processing an Add message, the new member SHOULD send an Update path from the updated leaf using the information contained in the Update message  <ins> The "update_secret" resulting from this change is the "path_secret[i+1]" derived from the "path_secret[i]" associated to the root node. </ins> 9.4. justifies the existence of a non-blank leaf in the ratchet tree in step 5.  <ins> The "update_secret" resulting from this change is the "path_secret[i+1]" derived from the "path_secret[i]" associated to the root node. </ins> 10.


cryptographic keys it holds.  An application or user may use one client per device (keeping keys local to each device) or sync keys among a user's devices so that each user appears as a single  client. A collection of clients with shared cryptographic state. negotiated MLS ciphersuite to AEAD encrypt and decrypt their Application messages according to the Message Framing section. <del> The group identifier and epoch allow a device to know which group </del>  secrets should be used and from which Epoch secret to start computing other secrets and keys.  The "sender" identifier is used to derive the member's Application secret chain from the initial group

cryptographic keys it holds.  An application or user may use one client per device (keeping keys local to each device) or sync keys among a user's devices so that each user appears as a single <ins> client.  In the scenario where multiple devices share the cryptographic material the client is referred to as a "virtual" </ins> client. A collection of clients with shared cryptographic state. negotiated MLS ciphersuite to AEAD encrypt and decrypt their Application messages according to the Message Framing section.  <ins> The group identifier and epoch allow a recipient to know which group </ins> secrets should be used and from which Epoch secret to start computing other secrets and keys.  The "sender" identifier is used to derive the member's Application secret chain from the initial group


Rename UserInitKey to ClientInitKey  draft-05 Common framing for handshake and application messages (*) The "tree_hash" is updated to represent the current tree and credentials <del> The "transcript_hash" is updated by a GroupOperation message "operation" in the following way: </del>  When a new one-member group is created (which requires no GroupOperation), the "transcript_hash" field is set to an all-zero

This PR addresses two issues that were noted in draft-05, one that is definitely a bug, and one that should improve security analysis. In draft-05, a circular dependency was introduced, wherein the confirmation MAC was calculated from the transcript, which includes the GroupOperation, which includes the confirmation MAC. Here we move the confirmation MAC up to the MLSPlaintext object to avoid this circularity. In all prior versions, the transcript covered only the GroupOperation objects, not the sender metadata or signatures. Here we cover the whole MLSPlaintext object, but in "staggered" form -- the confirmation MAC and signature aren't entered into the transcript until the next epoch.
Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 2 issues have been closed and 0 issues are still open. :heart: , by :heart: , by - - Last week, 4 pull requests were created, updated or merged. Last week, 4 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 9 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
Here's the Weekly Digest for : - - Last week 5 issues were created. Of these, 1 issues have been closed and 4 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by - - Last week, 9 pull requests were created, updated or merged. Last week, 3 pull requests were opened. :greenheart: , by :greenheart: , by :greenheart: , by Last week, 1 pull request was updated. :yellowheart: , by Last week, 5 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 8 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

Rename UserInitKey to ClientInitKey <ins> Resolve the circular dependency that draft-05 introduced in the confirmation MAC calculation (*) Cover the entire MLSPlaintext in the transcript hash (*) </ins> draft-05 Common framing for handshake and application messages (*) The "tree_hash" is updated to represent the current tree and credentials  <ins> The "transcript_hash" is updated with the data for an MLSPlaintext message encoding a group operation in two parts: This structure incorporates everything in an MLSPlaintext up to the confirmation field in the transcript that is included in that confirmation field (via the GroupState).  The confirmation and signature fields are then included in the transcript for the next operation.  The intermediate hash enables implementations to in corporate a plaintext into the transcript without having to store the whole MLSPlaintextOpAuthData structure. </ins> When a new one-member group is created (which requires no GroupOperation), the "transcript_hash" field is set to an all-zero


cases, the path is ordered from the leaf to the root; each node MUST be the parent of its predecessor. <del> The length of the "node_secrets" vector MUST be zero for the first </del>  node in the path.  For the remaining elements in the vector, the <del> number of ciphertexts in the "node_secrets" vector MUST be equal to </del>  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.

The underscore character does not have to be escaped in code environments. This applies to the inline (backticks) as well as block (tildes) variants.
Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 2 issues have been closed and 0 issues are still open. :heart: , by :heart: , by - - Last week, 4 pull requests were created, updated or merged. Last week, 4 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 9 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
Here's the Weekly Digest for : - - Last week 5 issues were created. Of these, 1 issues have been closed and 4 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by - - Last week, 9 pull requests were created, updated or merged. Last week, 3 pull requests were opened. :greenheart: , by :greenheart: , by :greenheart: , by Last week, 1 pull request was updated. :yellowheart: , by Last week, 5 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 8 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

cases, the path is ordered from the leaf to the root; each node MUST be the parent of its predecessor.  <ins> The length of the "node_secrets" vector MUST be zero for the first </ins> node in the path.  For the remaining elements in the vector, the  <ins> number of ciphertexts in the "node_secrets" vector MUST be equal to </ins> 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.


This structure incorporates everything in an MLSPlaintext up to the confirmation field in the transcript that is included in that <del> confirmation field (via the GroupState).  The confirmation and </del>  signature fields are then included in the transcript for the next operation.  The intermediate hash enables implementations to in corporate a plaintext into the transcript without having to store the

Race condition between and
Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 2 issues have been closed and 0 issues are still open. :heart: , by :heart: , by - - Last week, 4 pull requests were created, updated or merged. Last week, 4 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 9 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

This structure incorporates everything in an MLSPlaintext up to the confirmation field in the transcript that is included in that  <ins> confirmation field (via the GroupContext).  The confirmation and </ins> signature fields are then included in the transcript for the next operation.  The intermediate hash enables implementations to in corporate a plaintext into the transcript without having to store the


cases, the path is ordered from the leaf to the root; each node MUST be the parent of its predecessor. <del> The length of the "node_secrets" vector MUST be zero for the first node in the path.  For the remaining elements in the vector, the number of ciphertexts in the "node_secrets" 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>  The HPKECiphertext values are computed according to the Encrypt function defined in I-D.barnes-cfrg-hpke.

NAME pointed out this disconnect in , but the fix needs to be the other way around.
Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 2 issues have been closed and 0 issues are still open. :heart: , by :heart: , by - - Last week, 4 pull requests were created, updated or merged. Last week, 4 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 9 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

cases, the path is ordered from the leaf to the root; each node MUST be the parent of its predecessor.  <ins> The length of the "encrypted_path_secret" vector MUST be zero for the first node in the path.  For the remaining elements in the vector, 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. </ins> The HPKECiphertext values are computed according to the Encrypt function defined in I-D.barnes-cfrg-hpke.


group's rachet tree and the credentials for the members of the group, as described in tree-hashes. <del> The "transcript_hash" field contains the list of "GroupOperation" messages that led to this state. </del>  When a new member is added to the group, an existing member of the group provides the new member with a Welcome message.  The Welcome The "tree_hash" is updated to represent the current tree and credentials <del> The "transcript_hash" is updated with the data for an MLSPlaintext message encoding a group operation in two parts: </del>  This structure incorporates everything in an MLSPlaintext up to the confirmation field in the transcript that is included in that confirmation field (via the GroupContext).  The confirmation and signature fields are then included in the transcript for the next <del> operation.  The intermediate hash enables implementations to in corporate a plaintext into the transcript without having to store the </del>  whole MLSPlaintextOpAuthData structure. When a new one-member group is created (which requires no <del> GroupOperation), the "transcript_hash" field is set to an all-zero vector of length Hash.length, where the Hash algorithm is defined by the ciphersuite. </del>  6.5.

While trying to implement , I noticed that the confirmation and transcript hash calculations in draft-06 do not actually allow a new participant to join the transcript hash. Since the value is sent, and not the value, the new joiner is missing the auth data necessary to compute the next value. To fix this and clarify terminology, this PR makes the following changes: becomes , since this is what goes into the confirmation MAC becomes is updated to refer to the
Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 1 issues have been closed and 1 issues are still open. :greenheart: , by :heart: , by :speaker: , by It received 1 comments. - - Last week, 2 pull requests were created, updated or merged. Last week, 1 pull request was updated. :yellowheart: , by Last week, 1 pull request was merged. :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
This looks ok. If we want, merging and messages like in the TreeKEM paper would probably avoid some pain here. Merging.

group's rachet tree and the credentials for the members of the group, as described in tree-hashes.  <ins> The "confirmed_transcript_hash" field contains a running hash over the handshake messages that led to this state. </ins> When a new member is added to the group, an existing member of the group provides the new member with a Welcome message.  The Welcome The "tree_hash" is updated to represent the current tree and credentials  <ins> The "confirmed_transcript_hash" is updated with the data for an MLSPlaintext message encoding a group operation in two parts: </ins> This structure incorporates everything in an MLSPlaintext up to the confirmation field in the transcript that is included in that confirmation field (via the GroupContext).  The confirmation and signature fields are then included in the transcript for the next  <ins> operation.  The interim transcript hash is passed to new members in the WelcomeInfo struct, and enables existing members to incorporate a handshake message into the transcript without having to store the </ins> whole MLSPlaintextOpAuthData structure. When a new one-member group is created (which requires no  <ins> GroupOperation), the "interim_transcript_hash" field is set to the zero-length octet string. </ins> 6.5.


Key generation <del> Sign the protected content and metadata </del>  <del> Encrypt the sender information using the random nonce and the key derived from the sender_data_secret </del>  Encrypt the content using a content encryption key identified by the metadata The signature field in an MLSPlaintext object is computed using the signing private key corresponding to the credential at the leaf in the tree indicated by the sender field.  The signature covers the <del> metadata and message content, with the signature field truncated. </del>  The ciphertext field of the MLSCiphertext object is produced by supplying the inputs described below to the AEAD function specified Use the "confirmation_key" for the new epoch to compute the confirmation MAC for this message, as described below, and verify that it is the same as the "confirmation" field in the <del> GroupOperation object. </del>  If the the above checks are successful, consider the updated GroupContext object as the current state of the group.

Here's the Weekly Digest for : This week, 8 issues were created. Of these, 4 issues have been closed and 4 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :heart: , by The issue most discussed this week has been: :speaker: , by It received 9 comments. This week, no pull requests has been proposed by the users. This week, 4 users have contributed to this repository. They are , , , and . This week, no user has starred this repository. This week, there have been 4 commits in the repository. These are: :hammerandwrench: Merge pull request from rozbb/mlsplaintext-signature Multiple clarifications around Framing by :hammerandwrench: Merge pull request from rozbb/hpke-encrypt Clarify how HPKE ciphertexts are computed by :hammerandwrench: by :hammerand_wrench: by # RELEASES This week, no releases were published. That's all for this week, please watch :eyes: and star :star: to receive next weekly updates. :smiley:

Key generation  <ins> Sign the plaintext metadata - the group ID, epoch, sender index, and content type - as well as the message content </ins>  <ins> Randomly generate sender_data_nonce and encrypt the sender information using it and the key derived from the sender_data_secret </ins> Encrypt the content using a content encryption key identified by the metadata The signature field in an MLSPlaintext object is computed using the signing private key corresponding to the credential at the leaf in the tree indicated by the sender field.  The signature covers the  <ins> plaintext metadata and message content, i.e., all fields of MLSPlaintext except for the "signature" field. </ins> The ciphertext field of the MLSCiphertext object is produced by supplying the inputs described below to the AEAD function specified Use the "confirmation_key" for the new epoch to compute the confirmation MAC for this message, as described below, and verify that it is the same as the "confirmation" field in the  <ins> MLSPlaintext object. </ins> If the the above checks are successful, consider the updated GroupContext object as the current state of the group.


node.  Each ciphertext in the list is the encryption to the corresponding node in the resolution. <del> The HPKECiphertext values are computed according to the Encrypt function defined in I-D.barnes-cfrg-hpke. </del>  Decryption is performed in the corresponding way, using the private key of the resolution node and the ephemeral public key transmitted

node.  Each ciphertext in the list is the encryption to the corresponding node in the resolution.  <ins> The HPKECiphertext values are computed as where "node_public_key" is the public key of the node that the path secret is being encrypted for, and the functions "SetupBaseI" and "Seal" are defined according to I-D.barnes-cfrg-hpke. </ins> Decryption is performed in the corresponding way, using the private key of the resolution node and the ephemeral public key transmitted


current state using the Add message.  This information is encrypted for the new member using HPKE.  The recipient key pair for the HPKE encryption is the one included in the indicated ClientInitKey, <del> corresponding to the indicated ciphersuite. </del>  In the description of the tree as a list of nodes, the "credential" field for a node MUST be populated if and only if that node is a leaf

Prior drafts enabled encryption of handshake messages, via the common framing structure. This had the unfortunate effect of making it impossible to add new members! If an Add is sent encrypted, then the new joiner had no way to get the key to decrypt it. This PR adds the key and nonce for the Add encryption to the corresponding WelcomeInfo structure. This maintains the confidentiality of the Add because the WelcomeInfo is encrypted to the new joiner, while providing the new joiner the key material it needs to decrypt the Add.
I think we'll need to carefully study the impact of this one but this seems fine for now. In the future aligning the way we do and (for the new member) which both are PKE operations will probably allow us to merge and and remove that issue all together.

current state using the Add message.  This information is encrypted for the new member using HPKE.  The recipient key pair for the HPKE encryption is the one included in the indicated ClientInitKey,  <ins> corresponding to the indicated ciphersuite.  The "add_key_nonce" field contains the key and nonce used to encrypt the corresponding Add message; if it is not encrypted, then this field MUST be set to the null optional value. </ins> In the description of the tree as a list of nodes, the "credential" field for a node MUST be populated if and only if that node is a leaf


epoch's ratchet tree.  Each leaf in the AS Tree is associated with the same group member as the corresponding leaf in the ratchet tree. Nodes are also assigned an index according to their position in the <del> array representation of the tree (described in tree-math).  If V is a node in the AS Tree then IndexOf(V) denotes it's index while V.leftChild and V.rightChild denote the children of V (if they exist). </del>  Each node in the tree is assigned a secret.  The root's secret is simply the application_secret of that epoch.  (See key-schedule for the definition of application_secret.) The secret of any other node in the tree is derived from its parent's <del> secret using a call to Derive-Secret.  The context for the call is the (hash of the) Group state of the epoch and the index of the node whose secret is being derived. </del>  <del> If V is a node in the ASTree then ASTreeContext[V] denotes an ASTreeContext variable with: gshash = Hash(GroupState_[n]) node_index = IndexOf(V) Moreover, the secrets of the children of V are defined to be: </del>  Note that fixing concrete values for GroupState_[n] and application_secret completely defines all secrets in the AS Tree. used to encrypt more than one message. More precisely, the initial secret of the ratchet for the group <del> member assigned to the leaf with index i is simply the secret of that leaf. Keys, nonces and secrets of ratchets are derived using HKDF-Expand- Label.  The context in a given call consists of (a hash of) the current Group state, the index of the sender's leaf in the ratchet tree and the position in the ratchet.  In particular, the index of the sender's leaf in the ratchet tree is the same as the index of the leaf in the AS Tree used to initialize the sender's ratchet. Ratchet_position is initialized to 1 for the first HKDF-Expand-Label call of a new ratchet and incremented for each subsequent call in that ratchet. HashRatCont[i, j] denotes a RatchetContext variable where: gshash = Hash(GropuState_[n]) leaf_index = i ratchet_position = j </del>  <del> Using this notation the ratchet for the group member at leaf i is defined to be: </del>  <del> Here, AEAD.nonceLen and AEAD.keyLength denote the lengths in bytes of the nonce and key for the AEAD scheme defined by the ciphersuite. </del>  11.3. application_[i]_[j]_key and application_[i]_[j]_nonce. <del> Concretely, suppose we have the following AS Tree. </del>  Then if a client uses key KD1 and nonce ND1 during epoch n then it must consume (at least) values G, F, D0, D1, KD1, ND1 as well as the update_secret and init_secret used to derive G (i.e. the <del> application_secret). </del>  11.4.

This PR implements a collection of comments on . It aims to achieve the goal stated by NAME of having every derivation have a different relationship, but with a simpler construction.
Ok, I think this is good enough : )

epoch's ratchet tree.  Each leaf in the AS Tree is associated with the same group member as the corresponding leaf in the ratchet tree. Nodes are also assigned an index according to their position in the  <ins> array representation of the tree (described in tree-math).  If N is a node index in the AS Tree then left(N) and right(N) denote the children of N (if they exist). </ins> Each node in the tree is assigned a secret.  The root's secret is simply the application_secret of that epoch.  (See key-schedule for the definition of application_secret.) The secret of any other node in the tree is derived from its parent's  <ins> secret using a call to Derive-App-Secret. </ins>  <ins> If N is a node index in the ASTree then the secrets of the children of N are defined to be: </ins> Note that fixing concrete values for GroupState_[n] and application_secret completely defines all secrets in the AS Tree. used to encrypt more than one message. More precisely, the initial secret of the ratchet for the group  <ins> member assigned to the leaf with node index N is simply the secret of that leaf. </ins>  <ins> Keys, nonces and secrets of ratchets are derived using Derive-App- Secret.  The context in a given call consists of the index of the sender's leaf in the ratchet tree and the current position in the ratchet.  In particular, the index of the sender's leaf in the ratchet tree is the same as the index of the leaf in the AS Tree used to initialize the sender's ratchet. </ins>  <ins> Here, AEAD.nonce_length and AEAD.key_length denote the lengths in bytes of the nonce and key for the AEAD scheme defined by the ciphersuite. </ins> 11.3. application_[i]_[j]_key and application_[i]_[j]_nonce.  <ins> Concretely, suppose we have the following AS Tree and ratchet for participant D: </ins> Then if a client uses key KD1 and nonce ND1 during epoch n then it must consume (at least) values G, F, D0, D1, KD1, ND1 as well as the update_secret and init_secret used to derive G (i.e. the  <ins> application_secret).  The client MAY retain (i.e., not consume) the values KD0 and ND0 to allow for out-of-order delivery, and SHOULD retain D2 to allow for processing future messages. </ins> 11.4.


11.3. <del> It is important to delete all security sensitive values S as soon as they, or another value derived from them, is used for encryption or decryption. </del>  <del> More precisely, the values application_[i]_[j]_key and application_[i]_[j]_nonce are said to be "consumed" if they were used either to: </del>  <del> encrypt or (successfully) decrypt a message or </del>  <del> if a key, nonce or secret derived from S has been consumed. (This goes both for values derived via Derive-Secret and HKDF-Expand- Label.) Here, S may be the init_secret, update_secret, epoch_secret, application_secret as well as any secret in the AS Tree or one of the ratchets. </del>  As soon as a group member consumes a value they MUST immediately delete (all representations of) that value.  This is crucial to Then, for that member, at least the following values have been consumed and MUST be deleted: <del> the init_secret, update_secret, epoch_secret, application_secret of that epoch, </del>  all node secrets in the AS Tree on the path from the root to the leaf with index i, the first j secrets in the i-th ratchet and <del> application_[i]_[j]_key and application_[i]_[j]_nonce. </del>  Concretely, suppose we have the following AS Tree and ratchet for participant D:

Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 0 issues have been closed and 2 issues are still open. :greenheart: , by :greenheart: , by - - Last week, 8 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 5 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

11.3.  <ins> It is important to delete all security sensitive values as soon as they are _consumed_. A sensitive value S is said to be _consumed_ if </ins>  <ins> S was used to encrypt or (successfully) decrypt a message, or if </ins>  <ins> a key, nonce, or secret derived from S has been consumed.  (This goes for values derived via Derive-Secret as well as HKDF-Expand- Label.) </ins>  <ins> Here, S may be the "init_secret", "update_secret", "epoch_secret", "application_secret" as well as any secret in the AS Tree or one of the ratchets. </ins> As soon as a group member consumes a value they MUST immediately delete (all representations of) that value.  This is crucial to Then, for that member, at least the following values have been consumed and MUST be deleted:  <ins> the "init_secret", "update_secret", "epoch_secret", "application_secret" of that epoch, </ins> all node secrets in the AS Tree on the path from the root to the leaf with index i, the first j secrets in the i-th ratchet and  <ins> "application_[i]_[j]_key" and "application_[i]_[j]_nonce". </ins> Concretely, suppose we have the following AS Tree and ratchet for participant D:


specifies both (i) how a client performs the operation and (ii) how other clients update their state based on it. <del> There are four major operations in the lifecycle of a group: </del>  Adding a member, initiated by a current member;

The operations in the lifecycle of a group has been reduced to three.
Thank you !
Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 1 issues have been closed and 1 issues are still open. :greenheart: , by :heart: , by :+1: , by It received :+1: x1, :smile: x0, :tada: x0 and :heart: x0. :speaker: , by It received 1 comments. - - Last week, 3 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 1 pull request was updated. :yellowheart: , by Last week, 1 pull request was merged. :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustinsilhouette: - - Last week there were 3 stagazers. :star: :star: :star: You all are the stars! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

specifies both (i) how a client performs the operation and (ii) how other clients update their state based on it.  <ins> There are three major operations in the lifecycle of a group: </ins> Adding a member, initiated by a current member;


where "encode_big_endian()" encodes the generation in a big-endian integer of the same size as the base handshake nonce.  7. In order to facilitate asynchronous addition of clients to a group,

Note: There's a consistency issue around Derive-Secret, for which I filed for follow-up.
Here's the Weekly Digest for : - - Last week 4 issues were created. Of these, 0 issues have been closed and 4 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by - - Last week, 14 pull requests were created, updated or merged. Last week, 8 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 6 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 10 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 3 contributors. :bustinsilhouette: :bustinsilhouette: :bustinsilhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
On the one hand... On the other hand... We probably want Derive-Secret to have a third argument for the GroupContext, or define that Derive-Secret always takes the current group context.
I would much prefer to go back to the TLS definition, we don't need the thing at all, this is an implementation artifact... Definition we use for TLS and the symbolic proof in the formal model:
Ps: because is quite long in MLS, we directly pass to instead.
Here's the Weekly Digest for : - - Last week 11 issues were created. Of these, 1 issues have been closed and 10 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :speaker: , by It received 2 comments. - - Last week, 11 pull requests were created, updated or merged. Last week, 6 pull requests were opened. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by Last week, 4 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 1 pull request was merged. :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustin_silhouette: - - Last week there were 2 stagazers. :star: :star: You all are the stars! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 0 issues have been closed and 2 issues are still open. :greenheart: , by :greenheart: , by - - Last week, 8 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 5 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 1 issues have been closed and 1 issues are still open. :greenheart: , by :heart: , by :+1: , by It received :+1: x1, :smile: x0, :tada: x0 and :heart: x0. :speaker: , by It received 1 comments. - - Last week, 3 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 1 pull request was updated. :yellowheart: , by Last week, 1 pull request was merged. :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustinsilhouette: - - Last week there were 3 stagazers. :star: :star: :star: You all are the stars! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

where "encode_big_endian()" encodes the generation in a big-endian integer of the same size as the base handshake nonce. <ins> 6.9. The main MLS key schedule provides an "exporter_secret" which can be used by an application as the basis to derive new secrets called "exported_value" outside the MLS layer. The context used for the derivation of the "exported_value" MAY be empty while each application SHOULD provide a unique label as an input of the HKDF-Expand-Label for each use case.  This is to prevent two exported outputs from being generated with the same values and used for different functionalities. The exported values are bound to the Group epoch from which the "exporter_secret" is derived, hence reflects a particular state of the Group. It is RECOMMENDED for the application generating exported values to refresh those values after a group operation is processed. </ins> 7. In order to facilitate asynchronous addition of clients to a group,


the communicating endpoints, not any servers involved in delivering messages.  Establishing keys to provide such protections is challenging for group chat settings, in which more than two <del> participants need to agree on a key.  In this document, we specify a group key establishment protocol that provides efficient group key establishment with forward secrecy and post-compromise security. </del>  1. <del> [[ TODO - Group keying is necessary, but hard.  State of the art is sender keys, which have bad FS / PCS and bad rekey efficiency ]] </del>  2.

Also add myself as an author, and compensate for emacs's proclivities.
The goal of the reinit proposal is to trigger a tear down / restart of a group with the same members but different parameters such as a version upgrade, or a cipher suite change. Changing version - version is a field within key package, and this locks a key package to a specific version, even if capabilities allow for multiple versions. Should that field be removed, and instead you just look at capabilities? It seems that this would change with since leaf nodes will not be pinned to a specific version, just a cipher suite. After 575 gets merged one could upgrade versions using a new tree that copies the current non-empty leaves so long as each leaf has the upgraded version in their capabilities set. That specific tree building process is not mentioned, it is just sort of assumed in context. Changing cipher suite - In the case you want to change cipher suite, complexity somewhat increases. You will need to create a new tree by grabbing new key packages for each participant, and because the cipher suite has changed, all of the credentials have also changed. It is mentioned that "A group may be reinitialized by creating a new group with the same membership and different parameters", but this does not have a statement that has a SHOULD or MUST associated with it. For example, in my 5000 member group 1 member does not support the cipher suite that we are migrating away from. As the committer, I'm assuming that I should keep everyone in the group as best effort, but have the option to filter out problematic members that are blocking a migration due to them being offline for long periods of time or having outdated software. Due to the credential change, enforcing a MUST might be difficult since equality between two x509 credentials is not straight forward for example. To summarize, I propose some changes Remove version from key package, and rely on capabilities instead, this may now be irrelevant due to , but the version and capabilities.versions values seem duplicative Add some language in reinitialization that clarifies the flow for upgrading just version vs changing cipher suite, where changing cipher suite explicitly requires you acquire new key packages for each member. Clarify that a person issuing the welcome based on a reinit proposal SHOULD include all existing members
IMO those fields have quite separate purposes. Keep in mind that a different version could have a different KeyPackage format. So says "this KeyPackage is formatted according to this version", while the capabilities says what other versions I support. With that in mind, you need to grab new KeyPackages for everyone regardless of whether you're changing version, ciphersuite, or both. If this isn't clear, we should certainly clarify it. If you're worried about people not supporting the new stuff, you could maintain the hard semantic just by Removing those participants that don't support the new stuff before you ReInit.
Fair enough that seems reasonableI don't think it's necessarily clear right now, it's more of an assumption based on an understanding of the protocol overall. I'll try to come up with something there to give more of a step by step explanation of the flow.If this is a hard requirement should the doc say MUST here? If so, I'm trying to think through what equality means in terms of membership when in the event the cipher suite changes, all the credentials will also change.
On (3) -- I would be OK with saying that the new members MUST be the same as the old members. The notion of "same" is a little squishy, given ambiguities around identifiers, but it seems like it will probably be clear in practice. W.r.t. removing people to make an upgrade possible, when the application decides to upgrade and how the application it meets the same-member criterion is up to the application.
Discussion on virtual interim: Maybe put "remove before upgrade" in implementation considerations document.
NAME I meant to make this call to discuss, seem to not have the invite anymore, can you forward it to me? In terms of where this ticket is at, I was mostly raising the concerns to clarify for myself that what I think is the process is actually the process. I am willing to just close this one out

the communicating endpoints, not any servers involved in delivering messages.  Establishing keys to provide such protections is challenging for group chat settings, in which more than two  <ins> participants need to agree on a key but may not be online at the same time.  In this document, we specify a group key establishment protocol that provides efficient asynchronous group key establishment with forward secrecy and post-compromise security. </ins> 1.  <ins> 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; channels 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. For groups of size greater than two, the state of the art is to 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 is efficient and (with the addition of a hash ratchet) provides forward secrecy, it does not have post-compromise security.  An adversary who learns a sender key can therefore indefinitely and passively eavesdrop on that sender's messages. Rekeying, or generating new sender keys, provides a form of post- compromise security.  However, it requires a separate message to each potential receiver.  In this document we describe a tree-based system for deriving group keys which provides post-compromise security with efficient rekeys and without requiring any two parties to be online concurrently. </ins> 2.


A public key  A credential (only for leaf nodes) The conditions under which each of these values must or must not be A node in the tree may also be _blank_, indicating that no value is present at that node.  The _resolution_ of a node is an ordered list of non-blank nodes that collectively cover all non-blank descendants <del> of the node.  The nodes in a resolution are ordered according to their indices. </del>  <del> The resolution of a non-blank node is a one element list containing the node itself </del>  The resolution of a blank leaf node is the empty list For example, consider the following tree, where the "_" character represents a blank node: <del> In this tree, we can see all three of the above rules in play: </del>  <del> The resolution of node 5 is the list [CD] </del>  The resolution of node 2 is the empty list [] <del> The resolution of node 3 is the list [A, CD] </del>  <del> Every node, regardless of whether a node is blank or populated, has a corresponding _hash_ that summarizes the contents of the subtree </del>  below that node.  The rules for computing these hashes are described in tree-hashes. In particular, MLS maintains the members' views of the tree in such a way as to maintain the _tree invariant_: <del> In other words, each member holds the private keys for nodes in its direct path, and no others. </del>  5.4. compute the corresponding node secret and node key pair and replace the values stored at the node with the computed values.  For example, in order to communicate the example update described in the previous section, the sender would transmit the following values: If necessary, extend the tree to the right until it has at least index + 1 leaves  Blank the path from the leaf at position "index" to the root Set the leaf node in the tree at position "index" to a new node

This PR attempts to implement the "non-destructive add" proposal discussed at IETF 105. Instead of blanking nodes on add, we keep track of "unmerged leaves" below each intermediate node. This involves a bit more complexity in the tree state that is passed around, but avoids unnecessary blank nodes.
As discussed in the interim: Remove processing should be updated such that for each node in the removed node's direct path: If the removed leaf is in for the node, then just remove it from that list Otherwise, blank the node
Here's the Weekly Digest for : - - Last week 9 issues were created. Of these, 6 issues have been closed and 3 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :heart: , by :heart: , by :heart: , by :speaker: , by It received 2 comments. - - Last week, 13 pull requests were created, updated or merged. Last week, 3 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 10 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 38 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustin_silhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .*
Here's the Weekly Digest for : - - Last week, no issues were created. - - Last week, 5 pull requests were created, updated or merged. Last week, 3 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
Here's the Weekly Digest for : - - Last week 18 issues were created. Of these, 3 issues have been closed and 15 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :speaker: , by It received 5 comments. - - Last week, 10 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 7 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 4 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 4 contributors. :bustinsilhouette: :bustinsilhouette: :bustinsilhouette: :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 0 issues have been closed and 2 issues are still open. :greenheart: , by :greenheart: , by - - Last week, 8 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 5 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

A public key <ins> An ordered list of leaf indices for "unmerged" leaves (see views) </ins> A credential (only for leaf nodes) The conditions under which each of these values must or must not be A node in the tree may also be _blank_, indicating that no value is present at that node.  The _resolution_ of a node is an ordered list of non-blank nodes that collectively cover all non-blank descendants  <ins> of the node. </ins>  <ins> The resolution of a non-blank node comprises the node itself, followed by its list of unmerged leaves, if any </ins> The resolution of a blank leaf node is the empty list For example, consider the following tree, where the "_" character represents a blank node:  <ins> In this tree, we can see all of the above rules in play: </ins>  <ins> The resolution of node 5 is the list [CD, C] </ins> The resolution of node 2 is the empty list []  <ins> The resolution of node 3 is the list [A, CD, C] </ins>  <ins> Every node, regardless of whether the node is blank or populated, has a corresponding _hash_ that summarizes the contents of the subtree </ins> below that node.  The rules for computing these hashes are described in tree-hashes. In particular, MLS maintains the members' views of the tree in such a way as to maintain the _tree invariant_:  <ins> In other words, if node is not blank, then it holds a key pair, and the private key of that key pair is known only to members holding leaves below that node. The reverse implication is not true: A leaf below an intermediate node might not hold the private key for the node.  Such a leaf is called an _unmerged_ leaf, since encrypting to the subtree below the node requires encrypting to the node's public key as well as the unmerged leaves below it.  A leaf is unmerged when it is first added, because the process of adding the leaf does not give it access to all of the nodes above it in the tree.  Leaves are "merged" as they receive the private keys for nodes, as described in ratchet-tree- updates. </ins> 5.4. compute the corresponding node secret and node key pair and replace the values stored at the node with the computed values. <ins> For all updated nodes, set the list of unmerged leaves to the empty list. </ins> For example, in order to communicate the example update described in the previous section, the sender would transmit the following values: If necessary, extend the tree to the right until it has at least index + 1 leaves <ins> For each intermediate node along the path from the leaf at position "index" to the root, add "index" to the "unmerged_leaves" list for the node. </ins> Blank the path from the leaf at position "index" to the root Set the leaf node in the tree at position "index" to a new node


RFC EDITOR PLEASE DELETE THIS SECTION.  draft-07 Initial version of the Tree based Application Key Schedule (*)

Merging myself because this is trivial.
Here's the Weekly Digest for : - - Last week 3 issues were created. Of these, 1 issues have been closed and 2 issues are still open. :greenheart: , by :greenheart: , by :heart: , by :speaker: , by It received 1 comments. - - Last week, 6 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 1 pull request was updated. :yellowheart: , by Last week, 4 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 6 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

RFC EDITOR PLEASE DELETE THIS SECTION. <ins> draft-08 Change ClientInitKeys so that they only refer to one ciphersuite (*) </ins> draft-07 Initial version of the Tree based Application Key Schedule (*)


generate and publish multiple ClientInitKey objects to support multiple ciphersuites, or to reduce the likelihood of init key reuse. ClientInitKeys contain an identifier chosen by the client, which the <del> client MUST assure uniquely identifies a given ClientInitKey object </del>  among the set of ClientInitKeys created by this client. The value for init_key MUST be a public key for the asymmetric 8. Handshake and application messages use a common framing structure. <del> This framing provides encryption to assure confidentiality within the </del>  group, as well as signing to authenticate the sender within the group. messages encoded as MLSPlaintext objects in cases where it is necessary for the delivery service to examine such messages. <del> The remainder of this section describe how to compute the signature </del>  of an MLSPlaintext object and how to convert it to an MLSCiphertext object.  The overall process is as follows:

I don't like the pattern of having a marker byte followed by zero-padding. It has to be parsed manually, backwards, unlike every other object in the protocol which all follow a common format.
Agreement at the interim was that people don't care about the overhead (for now), so we're going to go with the simpler, TLS-syntax-based structure.
Here's the Weekly Digest for : - - Last week 18 issues were created. Of these, 3 issues have been closed and 15 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :speaker: , by It received 5 comments. - - Last week, 10 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 7 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 4 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 4 contributors. :bustinsilhouette: :bustinsilhouette: :bustinsilhouette: :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

generate and publish multiple ClientInitKey objects to support multiple ciphersuites, or to reduce the likelihood of init key reuse. ClientInitKeys contain an identifier chosen by the client, which the  <ins> client MUST ensure uniquely identifies a given ClientInitKey object </ins> among the set of ClientInitKeys created by this client. The value for init_key MUST be a public key for the asymmetric 8. Handshake and application messages use a common framing structure.  <ins> This framing provides encryption to ensure confidentiality within the </ins> group, as well as signing to authenticate the sender within the group. messages encoded as MLSPlaintext objects in cases where it is necessary for the delivery service to examine such messages.  <ins> The remainder of this section describes how to compute the signature </ins> of an MLSPlaintext object and how to convert it to an MLSCiphertext object.  The overall process is as follows:


supports, as well as providing a public key that others can use for key agreement.  The client's identity key is intended to be stable throughout the lifetime of the group; there is no mechanism to change <del> it.  Init keys are intended to be used a very limited number of times, ideally only once.  (See init-key-reuse).  Clients MAY generate and publish multiple ClientInitKey objects to support multiple ciphersuites, or to reduce the likelihood of init key reuse. ClientInitKeys contain an identifier chosen by the client, which the client MUST ensure uniquely identifies a given ClientInitKey object among the set of ClientInitKeys created by this client. </del>  The value for init_key MUST be a public key for the asymmetric encryption scheme defined by cipher_suite.  The whole structure is 13.4. Initialization keys are intended to be used only once and then <del> deleted.  Reuse of init keys is not believed to be inherently insecure dhreuse, although it can complicate protocol analyses. </del>  14.

This has been reported unclear multiple times. I strongly prefer forbidding reuse altogether. A validation mechanism is needed for the formal security proof, it can be implemented according to an expiration mechanism (see Architecture - 4.2. Delivery Service Compromise)
We need to allow Last Resort keys. Not sure what you mean by "replay attacks"
I rewrote it in favor of using "SHOULD NOT reuse", which is true, except in case of last resort to avoid DOS, which we are willing to allow. Normal meaning... If I remember correctly, there is a cross channel forwarding attack (replay) possible on the first message in Signal when reusing prekeys (the last resort key) because it lacks some channel binding but I would have to check. I am working to make sure we don't suffer the same defect but I am documenting it in the mean time.
I can live with this for now; we can refine later.
Here's the Weekly Digest for : - - Last week 9 issues were created. Of these, 6 issues have been closed and 3 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :heart: , by :heart: , by :heart: , by :speaker: , by It received 2 comments. - - Last week, 13 pull requests were created, updated or merged. Last week, 3 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 10 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 38 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustin_silhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .*
Here's the Weekly Digest for : - - Last week, no issues were created. - - Last week, 5 pull requests were created, updated or merged. Last week, 3 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
Here's the Weekly Digest for : - - Last week 18 issues were created. Of these, 3 issues have been closed and 15 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :speaker: , by It received 5 comments. - - Last week, 10 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 7 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 4 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 4 contributors. :bustinsilhouette: :bustinsilhouette: :bustinsilhouette: :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

supports, as well as providing a public key that others can use for key agreement.  The client's identity key is intended to be stable throughout the lifetime of the group; there is no mechanism to change  <ins> it.  Init keys are intended to be used only once and SHOULD NOT be reused except in case of last resort.  (See init-key-reuse).  Clients MAY generate and publish multiple ClientInitKey objects to support multiple ciphersuites.  ClientInitKeys contain an identifier chosen by the client, which the client MUST ensure uniquely identifies a given ClientInitKey object among the set of ClientInitKeys created by this client. </ins> The value for init_key MUST be a public key for the asymmetric encryption scheme defined by cipher_suite.  The whole structure is 13.4. Initialization keys are intended to be used only once and then  <ins> deleted.  Reuse of init keys can lead to replay attacks. </ins> 14.


public keys are opaque values in a format defined by the signature scheme.  6.4. To allow group members to verify that they agree on the cryptographic

I couldn't find this written anywhere else and this is also related to a discussion about PCS with Cas and al.
Here's the Weekly Digest for : - - Last week, no issues were created. - - Last week, 5 pull requests were created, updated or merged. Last week, 3 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
Here's the Weekly Digest for : - - Last week 18 issues were created. Of these, 3 issues have been closed and 15 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :speaker: , by It received 5 comments. - - Last week, 10 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 7 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 4 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 4 contributors. :bustinsilhouette: :bustinsilhouette: :bustinsilhouette: :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

public keys are opaque values in a format defined by the signature scheme. <ins> Note that each new credential that has not already been validated by the application SHOULD be validated against the Authentication Service. [[OPEN ISSUE: 1.  SHOULD vs MUST.  2.  A client that wants to update its identity key can perform the operation UNDER THIS CONDITION by adding a new version of herself using a new credential signed under a new IdentityKey, then performing a remove of the old leaf.  This is fine as long as the credential binds to the same identity for the application.  If this verfication is not met, there is no authentication guarantee at the application layer anyway.]] </ins> 6.4. To allow group members to verify that they agree on the cryptographic


The resolution of a blank leaf node is the empty list The resolution of a blank intermediate node is the result of <del> concatinating the resolution of its left child with the resolution </del>  of its right child, in that order For example, consider the following tree, where the "_" character

This PR corrects three minor typos.
Thank you Pascal !
Here's the Weekly Digest for : - - Last week 18 issues were created. Of these, 3 issues have been closed and 15 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :speaker: , by It received 5 comments. - - Last week, 10 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 7 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 4 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 4 contributors. :bustinsilhouette: :bustinsilhouette: :bustinsilhouette: :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

The resolution of a blank leaf node is the empty list The resolution of a blank intermediate node is the result of  <ins> concatenating the resolution of its left child with the resolution </ins> of its right child, in that order For example, consider the following tree, where the "_" character