Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LightCommit is problematic #6

Open
bifurcation opened this issue Aug 22, 2024 · 1 comment
Open

LightCommit is problematic #6

bifurcation opened this issue Aug 22, 2024 · 1 comment

Comments

@bifurcation
Copy link
Collaborator

The current LightCommit struct has some drawbacks. It seems simple on the surface because it's just a GroupInfo, but:

  • It can't be generated by the DS, only a member.
  • It doesn't prove that the recipient is still in the group. (maybe not necessary, but seems nice to have)
  • It requires extra extensions in the GroupInfo.
  • It requires different tree_info validation / production logic than Welcome
    • Welcome requires that the sender membership proof validate against the tree hash in the GroupInfo
    • Here, the membership proof should validate against the tree hash for the prior epoch
  • It can't represent a commit in which PSKs were added.

It seems to me that a better approach would be something like the following:

// OPTION B
struct LightCommit {
  GroupInfo group_info; // with tree_info extension relative to old tree hash
  TreeSlice recipient_membership_proof; // relative to the new tree hash
  EncryptedPathSecret encrypted_path_secret;
  PreSharedKeyID psks<V>;
}

This re-uses the GroupInfo with tree_info scheme (including the current/prior epoch weirdness), but moves the other information outside the signed envelope so that the DS can add it. The information is ultimately confirmed by the confirmation_tag in the GroupInfo, so it should be safe for the DS to add.

Option B is still a little unfortunate because it requires a committer to send both a GroupInfo and a Commit. This could be challenging for incremental deployment in a setting where committers aren't already sending GroupInfo alongside Commit, since it would require a behavior change at the committer as well as the light client. Another option that avoids that drawback would be something like:

// OPTION C
struct AnnotatedCommit {
  MLSMessage commit;
  TreeSlice sender_membership_proof; // relative to the old tree hash
  TreeSlice recipient_membership_proof; // relative to the new tree hash
  uint32 resolution_index;
  PreSharedKeyID psks<V>;
  Extension extensions<V>;
};

This can be generated by the DS based only on a Commit, and it avoids the tree_info old/new epoch weirdness. It also gets an extensions field in case of GroupContextExtensions proposals. (The confirmed_transcript_hash can be computed as usual.) The light client locates its HPKECiphertext in the UpdatePath by finding the first / lowest-level overlap with the direct path in its membership proof, then using the resolution_index to select from the individual encryptions. Obviously this is no longer really "light", though, because it carries the whole Commit, which can get heavy.

It seems like either B or C would be an update for the current state. It might be worth defining both, since they can cleanly coexist, and address different use cases.

@bifurcation
Copy link
Collaborator Author

FWIW, I have gotten the following flavor of AnnotatedCommit working in MLSpp:

struct AnnotatedCommit {
  MLSMessage commit_message;

  bytes tree_hash_after;
  TreeSlice sender_membership_proof_before;
  TreeSlice sender_membership_proof_after;
  TreeSlice receiver_membership_proof_after;

  optional<uint32_t> resolution_index;
};

Working in the sense of:

  • Having the DS logic to produce an AnnotatedCommit from a Commit, a set of Proposals, and the trees before and after the commit
  • Being able to update a light client's state from one epoch to the next using an AnnotatedCommit
  • Verifying that the updated stack passes the passive client test vectors, with the DS logic generating each epoch's ratchet tree and producing AnnotatedCommits from the Proposals and Commits in the test vector file.

The DS logic to figure out which node in a Commit belongs to a given receiver is slightly non-trivial, but not terrible. It mostly worked on the first try, except for one bug that didn't show up until pretty far into the random-commits test vector.

All in all, this seems like a worthwhile thing to write up, at least as a transitional measure from a domain where clients don't produce GroupInfo already. (Note that it's possible to support LightCommit and AnnotatedCommit at the same time; the state in a light client is the same.) I'll work on some text.

The above structure might not be minimal. Or might not be secure! (But it seems OK?) Suggestions for improvement welcome. I already stripped out the extensions and psks fields, because you can get those from proposals.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant