Change:
This PR makes two major changes that are enabled by Proposals: Multiple participants added in the same epoch receive the same Welcome message Init is always a special case of Add Prior to Proposals, treating Init as a special case of Add led to a performance degradation (). With Proposals, any number of Adds can be done with a single Commit (at cost), so there is no more degradation. The result seems (IMO) much more elegant than before. The main cost is that encryption of Welcome messages is now in two stages (three if you include the internal HPKE stage!), even if there is only one new member. Depends on Obsoletes and
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 .*
Instead of initializing new members with information from the previous epoch and requiring them to process an Add, we should initialize new members directly with current epoch information. This is covered in , but should be factored out.
Dependent on: Some modeling to convince ourselves that removing isn't dangerous Blocks:
I have made a Tamarin model of the 2- and 3-member cases of the proposal in , which shows that it provides certain authentication properties that one should expect of an AKE. In particular, it provides the property that even if the adder is malicious, they cannot cause the new member and the existing members to come to differing views of the group without causing to group to decohere. (Since the GroupContext is included in the key schedule, this might not be surprising.) Tamarin model here: URL Given this analysis, I'm comfortable making this change. It's preliminary, but I think it's good enough to justify moving forward with this concept pending a more complete analysis.
Fixed in
Modulo fixes discussed with Richard

Discussion:
Enable Add and Remove proposals from outside the group (*) <ins> Replace Init messages with multi-recipient Welcome message (*) </ins> draft-07 Initial version of the Tree based Application Key Schedule (*)

9. <del> A client creates a group with a specified set of initial members by constructing an Init message and sending it to those members. The creator of the group constructs an Init message as follows: Fetch one or more ClientInitKeys for each member (including the creator) Identify a protocol version and ciphersuite that is supported by all proposed members. </del> <ins> A group is always created with a single member, the "creator".  The other members are added when the creator effectively sends itself an Add proposal and commits it, then sends the corresponding Welcome message to the new participants.  These processes are described in detail in add, commit, and welcoming-new-members. </ins> <del> Construct a ratchet tree with its leaves populated with the public keys and credentials from the ClientInitKeys of the members, and all other nodes blank. </del> <ins> The creator of a group MUST take the following steps to initialize the group: </ins> <del> Generate a fresh leaf key pair for the first leaf </del> <ins> Fetch ClientInitKeys for the members to be added, and selects a version and ciphersuite according to the capabilities of the members. [[ TODO: Discuss downgrade prevention here ]] </ins> <del> Compute its direct path in this ratchet tree </del> <ins> Initialize a one-member group with the following initial values (where "0" represents an all-zero vector of size Hash.length): </ins> <del> Each member of the newly-created group initializes its state from the Init message as follows: </del> <ins> Ratchet tree: A tree with a single node, a leaf containing an HPKE public key and credential for the creator </ins> <del> Verify that all of the ClientInitKeys listed are for the same protocol and ciphersuite; if not, reject the Init as malformed </del> <ins> Group ID: A value set by the creator </ins> <del> Note the group ID, protocol version, and ciphersuite in use. </del> <ins> Epoch: 0x00000000 </ins> <del> Construct a ratchet tree as above </del> <ins> Tree hash: The root hash of the above ratchet tree </ins> <del> Update the cached ratchet tree by replacing nodes in the direct path from the first leaf using the direct path </del> <ins> Confirmed transcript hash: 0 </ins> <del> Update the cached ratchet tree by replacing nodes in the direct path from the first leaf using the information contained in the "path" attribute </del> <ins> Interim transcript hash: 0 </ins> <del> The epoch secret for the first epoch is computed from: </del> <ins> Init secret: 0 </ins> <del> An all-zero init secret </del> <ins> For each member, construct an Add proposal from the ClientInitKey for that member (see add) </ins> <del> An update secret "path_secret[i+1]" derived from the "path_secret[i]" associated to the root node </del> <ins> Construct a Commit message that commits all of the Add proposals, in any order chosen by the creator (see commit) </ins> <del> A GroupContext object resulting from the above initialization </del> <ins> Process the Commit message to obtain a new group state (for the epoch in which the new members are added) and a Welcome message </ins> <del> The members learn the relevant path secrets by decrypting one of the encrypted path secrets in the DirectPath and working back to the root (as in normal DirectPath processing). </del> <ins> Transmit the Welcome message to the other new members </ins> <del> Note the degenerate case of this process: The group creator can initialize a group with one member (itself) and add the remaining members by sending Add proposals followed by a Commit.  This approach is slightly more verbose than simply sending an Init message, but also slightly more private.  The Init leaks the initial configuration of the group, while in the Add approach, the initial group state is sent in encrypted Welcome messages. </del> <ins> The recipient of a Welcome message processes it as described in welcoming-new-members. </ins> <del> [[ OPEN ISSUE: It might be better to collapse these two approaches. This would entail sending multiple Proposals alongside a Commit and encrypting a Welcome to multiple participants, both of which seen like nice optimizations anyway. ]] </del> <ins> In principle, the above process could be streamlined by having the creator directly create a tree and choose a random value for first epoch's epoch secret.  We follow the steps above because it removes unnecessary choices, by which, for example, bad randomness could be introduced.  The only choices the creator makes here are its own HPKE key and credential, the leaf secret from which the Commit is built, and the intermediate key pairs along the direct path to the root. </ins> <del> [[ OPEN ISSUE: It might be desireable for the group creator to be able to "pre-warm" the tree, by providing values for some nodes not on its direct path.  This would violate the tree invariant, so we would need to figure out what mitigations would be necessary. ]] </del> <ins> A new member receiving a Welcome message can recognize group creation if the number of entries in the "members" array is equal to the number of leaves in the tree minus one.  A client receiving a Welcome message SHOULD verify whether it is a newly created group, and if so, SHOULD verify that the above process was followed by reconstructing the Add and Commit messages and verifying that the resulting transcript hashes and epoch secret match those found in the Welcome message. </ins> 10.

10.2.1. <del> The sender of a Commit message is responsible for sending Welcome messages to any new members added via Add proposals.  The Welcome message provides the new member with the current state of the group, after the application of the Commit message.  So the new member will </del> <ins> The sender of a Commit message is responsible for sending a Welcome message to any new members added via Add proposals.  The Welcome message provides the new members with the current state of the group, after the application of the Commit message.  The new members will </ins> not be able to decrypt or verify the Commit message, but will have <del> the secrets it needs to participate in the epoch initiated by the </del> <ins> the secrets they need to participate in the epoch initiated by the </ins> Commit message. <del> The information in a Welcome message 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> <ins> In order to allow the same Welcome message to be sent to all new members, information describing the group is encrypted with a symmetric key and nonce randomly chosen by the sender.  This key and nonce are then encrypted to each new member using HPKE.  In the same encrypted package, the committer transmits the path secret for the lowest node contained in the direct paths of both the committer and the new member.  This allows the new member to compute private keys for nodes in its direct path that are being reset by the corresponding Commit. </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 <del> in the tree. </del> <ins> in the tree (i.e., a node with an even index). On receiving a Welcome message, a client processes it using the following steps: </ins> <del> [[ OPEN ISSUE: If multiple members are being added, it would be nice to be able to encrypt the group state once and just encrypt the key to the members.  In that case, you would also need to factor out the "index" field. ]] </del> <ins> Identify an entry in the "key_packages" array where the "client_init_key_hash" value corresponds to one of this client's ClientInitKeys, using the hash indicated by the "cipher_suite" field.  If no such field exists, or if the ciphersuite indicated in the ClientInitKey does not match the one in the Welcome message, return an error. Decrypt the "encrypted_key_package" using HPKE with the algorithms indicated by the ciphersuite and the HPKE public key in the ClientInitKey. Decrypt the "encrypted_group_info" field using the key and nonce in the decrypted KeyPackage object. Verify the signature on the GroupInfo object.  The signature input comprises all of the fields in the GroupInfo object except the signature field.  The public key and algorithm are taken from the credential in the leaf node at position "signer_index".  If this verification fails, return an error. Identify a leaf in the "tree" array (i.e., an even-numbered node) whose "public_key" and "credential" fields are identical to the corresponding fields in the ClientInitKey.  If no such field exists, return an error.  Let "index" represent the index of this node among the leaves in the tree, namely the index of the node in the "tree" array divided by two. Construct a new group state using the information in the GroupInfo object.  The new member's position in the tree is "index", as defined above. Identify the lowest node at which the direct paths from "index" and "signer_index" overlap.  Set private keys for that node and its parents up to the root of the tree, using the "path_secret" from the KeyPackage and following the algorithm in ratchet-tree- updates to move up the tree. </ins> 11.