GithubHelp home page GithubHelp logo

mls-protocol's People

Contributors

beurdouche avatar bifurcation avatar br-hale avatar bren2010 avatar chelseakomlo avatar claucece avatar d1vyank avatar ekr avatar eomara avatar ericcornelissen avatar franziskuskiefer avatar gaphil avatar jmillican avatar katrielalex avatar kelrit avatar kkohbrok avatar martamularczyk avatar mulmarta avatar pjunodsc avatar psyoptix avatar raphaelrobert avatar rohan-wire avatar rozbb avatar seanturner avatar stefunctional avatar suhashere avatar tomleavy avatar twal avatar uhoreg avatar yihuang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mls-protocol's Issues

Provide signals to support better FS

If a group member can signal what its latest epoch is (e.g., by ACKing a handshake message), then other members know that they can safely delete any keys older than that epoch, at least for that sender.

Add-in-Place / Garbage Collection

Currently, the tree only ever grows:

  • When you add someone, you have to add them at the right edge, even if there are blank leaves
  • When you remove someone, the tree never shrinks

We should enable reclaiming of blank leaves and automatically reduce the size of the tree to the minimum necessary size.

Retry considerations

We have some text about how Handshake messages need to be sequenced, but clients will need some retry logic to deal with cases where there's a gap between the premise for their action and the state of the group when the action can be taken. We should describe the logic a client should follow for retrying with each of the available operations. For example, Update can just be retried, but Add and Remove should be checked for duplication before retrying.

Some undefined terms and primitives

I think a bunch of these are probably relics of previous versions. For reference, the page numbers listed are from the PDF version of draft 3 of the protocol:

  • 1 - p6: GroupInit is mentioned, but it is not defined anywhere in the specification. Perhaps Init is intended.

  • 2 - p19: A transcript field is mentioned, but only transcript_hash is present. Also it's unclear which Hash function is supposed to be used here. It can't be ciphersuite-dependent, since it has to be the same for every Participant.

  • 3 - p22: update_secret is used in a diagram, but never defined. I think this is important, and it's mentioned elsewhere.

  • 4 - p24: finished_mac is mentioned, but never defined. Is it supposed to say confirmation?

  • 5 - p25: The underlying Hash that HMAC uses can't be defined by anyone's ciphersuite. This is group state, and everyone has to agree on this.

  • 6 - p28: Mentioned "update secret" again without explanation.

  • 7 - p29: "identity tree" is mentioned, but I can't tell what that's referring to. Also "update secret" is here.

  • 8 - p35: MLSPlaintext is mentioned, but never defined. Perhaps ApplicationPlaintext is intended.

STROBE

There is a nifty advantage of using Mike Hamburg's STROBE for symmetric cryptography:

Applications using WASM virtual machines should improve performance by using native code for cryptography. STROBE works well for this because all actual processing is handled by one call that processes an arbitrary amount of data. You always require multiple STROBE calls per operation in practice of course, but only O(1) cals. If you wrapped say a ChaCha or Keccak permutation directly then youโ€™d have O(data_size) calls. In short, STROBE simplifies the WASM call boundary dramatically without much performance penalty.

In MLS, you might favor adding ChaCha into your WASM call boundary anyways because STROBE lacks any round count configuration. I wanted to mention this however since messengers do commonly get implemented in VMs.

Replay protection

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 #101 if we want to solve it at that framing layer.

Advertize a global app generation for a sender

We could use the sender_generation field of the MLS message to signal what was the global app generation of the sender. Functionally, this allows receivers to know if they received all previous application messages from the sender. In the current design, if S sent M0, M1, M2 you can know if you missed M1 when receiving M2, but you cannot know if you missed M2. There are many ways of doing this: global sender counter, counter between two operations of the sender...

Weekly Digest (19 April, 2019 - 26 April, 2019)

Here's the Weekly Digest for mlswg/mls-protocol:


ISSUES

Last week 4 issues were created.
Of these, 1 issues have been closed and 3 issues are still open.

OPEN ISSUES

๐Ÿ’š #153 Common framing, consolidated, by bifurcation
๐Ÿ’š #152 Make epochs unpredictable, by bifurcation
๐Ÿ’š #150 Allow direct initialization, by bifurcation

CLOSED ISSUES

โค๏ธ #151 A couple of minor fixes, by bifurcation

NOISY ISSUE

๐Ÿ”ˆ #152 Make epochs unpredictable, by bifurcation
It received 4 comments.


PULL REQUESTS

Last week, 9 pull requests were created, updated or merged.

UPDATED PULL REQUEST

Last week, 8 pull requests were updated.
๐Ÿ’› #153 Common framing, consolidated, by bifurcation
๐Ÿ’› #152 Make epochs unpredictable, by bifurcation
๐Ÿ’› #148 Added that users SHOULD verify pubkeys in an Update, by rozbb
๐Ÿ’› #147 Added public_key_index to Add message, by rozbb
๐Ÿ’› #146 Tree based app keyschedule, by psyoptix
๐Ÿ’› #143 Fixes to tree manipulation in Remove, by rozbb
๐Ÿ’› #134 Tree Hash, by bifurcation
๐Ÿ’› #131 Common Framing, by beurdouche

MERGED PULL REQUEST

Last week, 1 pull request was merged.
๐Ÿ’œ #151 A couple of minor fixes, by bifurcation


COMMITS

Last week there were 4 commits.
๐Ÿ› ๏ธ Merge pull request #151 from mlswg/minor-fixes A couple of minor fixes by bifurcation
๐Ÿ› ๏ธ Fix error noted by @rozbb by bifurcation
๐Ÿ› ๏ธ Make welcome/add diagram clearer by bifurcation
๐Ÿ› ๏ธ Open issue cleanup by bifurcation


CONTRIBUTORS

Last week there was 1 contributor.
๐Ÿ‘ค bifurcation


STARGAZERS

Last week there was 1 stargazer.
โญ Mromson
You are the star! ๐ŸŒŸ


RELEASES

Last week there were no releases.


That's all for last week, please ๐Ÿ‘€ Watch and โญ Star the repository mlswg/mls-protocol to receive next weekly updates. ๐Ÿ˜ƒ

You can also view all Weekly Digests by clicking here.

Your Weekly Digest bot. ๐Ÿ“†

Simplify the key schedule

Currently, the whole GroupState object is folded into the key schedule, via the DeriveSecret function. Could this be simplified? For example:

  • Hash the GroupState object once, and use it for all DeriveSecret calls, as opposed to passing it by value each time

  • Hash in the roster and tree as a commitment (cf #87) rather than by value

Other suggestions welcome.

Version negotiation

We need some story for how to evolve versions over time. How and where is version support indicated? How can a group transition from one version to another?

Encryption of Welcome messages

This was resolved in #80, but recording it in this issue for posterity. A Welcome message carries the init_secret value for the group, and so it needs to be encrypted for the new joiner.

The struct proposed in the revised draft wraps the information in the Welcome in an ECIES ciphertext, and adds enough information to enable the joiner to identify the private key it needs to decrypt the Welcome message.

struct {
  opaque group_id<0..255>;
  uint32 epoch;
  optional<Credential> roster<1..2^32-1>;
  optional<PublicKey> tree<1..2^32-1>;
  opaque transcript_hash<0..255>;
  opaque init_secret<0..255>;
} WelcomeInfo;

struct {
  opaque user_init_key_id<0..255>;
  CipherSuite cipher_suite;
  ECIESCiphertext encrypted_welcome_info;
} Welcome;

CIK rotation

Security considerations should provide guidance about how often to rotate, last resort, etc.

Use common framing

We have several types of top-level objects right now:

  • UserInitKey messages
  • Welcome messages
  • Handshake messages
  • Application messages

We should have a common framing layer that describes the object type (and optionally provides encryption), to prevent confusion among these types. This would be analogous to the TLS record layer

"Pre-warm" trees with some double-joined nodes

In the current draft, creating a group is done with n Add messages, which just place the members of the group at the leaves of the tree. This means that newly-created trees have some "warm up" time during which early operations are roughly linear size, gradually converging to log size.

This state of affairs is unavoidable if we are not going to have double joins. However, it might be tolerable to have double joins, so long as (1) they only happen at group creation time and (2) they resolve relatively quickly.

For example, you might create a special Init message, distinct from Add, which initializes a tree with the members at the leaves, but also some intermediate nodes filled in by the creator (and thus double-joined). These nodes would be overwritten as members update, but the double-joins would only be fully resolved once all members update (or 1/2^{k} of the members if k lower layers are not double-joined).

Application key schedule is busted

There are at least two bugs in the message protection section that make it unimplementable:

  1. It calls for Derive-Secret(., "app sender", [sender]), but the third argument to Derive-Secret as defined is a GroupState, not an octet string.

  2. It refers to a function HKDF-Expand-Label, which is defined in TLS, but not here.

ISTM the simplest way to fix these problems would to define HKDF-Expand-Label and use it (1) as the basis for Derive-Secret, (2) for deriving sender root secrets, and (3) for deriving keys and nonces.

Prevent suppression of Handshake messages

In current proposals, it is possible for the delivery service to distinguish handshake and application messages. This enables the DS to lock in a compromise by forbidding key updates while allowing application messaging to continue. We should make it harder to distinguish handshake and application messages, e.g., by encrypting the content type.

Syntax unification

We inconsistently use the backtick, the underscore or nothing for messages fields or specific operations in the draft. This needs a fix, currently the opinion is to use the TLS style (aka remove everything)

State resync

Sometimes a client falls out of sync with the rest of the group, and it is necessary to re-initialize it. What protocol mechanisms are necessary to make this possible?

  • How do endpoints discover that they have lost sync?
  • How do they resync?
  • Who can provide resync data? the server? other clients?

Perhaps it would be useful to look at the state of the art with regard to how desync occurs and how it repaired.

s5.1. _subtree_ definition

I think there's something missing from the following sentence in s5.1:

A _subtree_ of a tree is the tree given by the descendants of any
node, the _head_ of the subtree The _size_ of a tree or subtree is
the number of leaf nodes it contains.

Discuss all the *ART deletion options

We talked about quite a number of different ways to do deletion in *ART groups. Give at least a high-level overview of the main ones, and mention their pros and cons. These include:

  • just rebuild the tree
    • Pros: simple, easy, no extra operations
    • Cons: inefficient, puts the deleter in a trusted position in the group until every remaining member has updated
  • update deletee's key to blank
    • Pros: fairly simple, no extra operations
    • Cons: puts the deleter in a trusted position until the sibling or cousin of the deletee has updated
  • send a delete secret over pairwise channels
    • Pros: no trusted positions
    • Cons: O(N), leaves a potentially-compromised leaf node in the tree
  • send a delete secret by KEMing to everyone else
    • Pros: no trusted positions, efficient
    • Cons: leaves a potentially-compromised leaf node in the tree, multiple deletes interact in a complex way

ACK / NACK

In early discussions around MLS, people expressed interest in specifying how to do ACKs / NACKs on messages. Questions to address:

  • How are ACKs / NACKs encoded?
  • How are they cryptographically protected? (signed, encrypted, MAC'ed, etc.)
  • When should they be sent?
  • Do they apply to handshake messages? application messages? both?

Handshake message parsing is ambiguous in type-safe implementations

At least 2 existing implementations of MLS have some sort of curve-specific DH public key type. This is to ensure type safety and reduce the likelihood of the programmer accidentally using one point value for a different curve. For me, this is

enum DhPoint {
    X25519([u8; 32]),
    P256([u8; 32]),
}

The issue I run into is that I cannot unambiguously deserialize DHPublicKeys into a DHPoint. Recall the definition opaque DHPublicKey<1..2^16-1>. The parse of an unmarked sequence of bytes is dependent on ambient state, namely the CipherSuite of the current session. Notably, the value of this CipherSuite is not repeated in any top-level messages. This means that a given Handshake message will have at least two correct interpretations unless context is specified.

This is not a massive issue, but one could imagine a case where a participant receives a message from another participant who somehow disagrees on the current CipherSuite. The receiver will parse all the messages correctly, check the signatures, and throw an invalid signature error. If we were to mark the type of the DHPublicKey, though, the receiver would parse the values and check that they agree with the current CipherSuite. This check will fail, and it will throw a decoherence error, which is more appropriate and informative.

DHPublicKey is not the only data type for which this ambiguity occurs. I propose that we change at least some opaque datatypes to enums. Currently, the not-really-bytes opaque types are

  • DHPublicKey
  • SignaturePublicKey
  • ECIES::ciphertext
  • UserInitKey::signature
  • Handshake::signature
  • ApplicationPlaintext::signature
  • Application::encrypted_content

My own implementation makes distinctions between different signature types, ECDSA pubkey types, and ECDH pubkey types. Encrypted content is treated as a binary blob.

Allow direct initialization

We have a long-standing OPEN ISSUE on creating a group with a single Init message instead of N Add messages, which would change the work of initialization from O(N log N) to O(N). I would propose roughly the following:

struct {
    Welcome creator_info<0..2^32-1>; // Welcome from one-member group to each joiner
    UserInitKey members<0..2^32-1>; // Info to populate at the leaves
    DirectPath creator_update; // Update from the creator to warm the tree
} Init;

Then the processing would be:

  • Find the welcome that's for you
  • Initialize a one-member tree from the Welcome
  • Use the UserInitKeys to populate the leaves of the tree
  • Use the DirectPath to populate the creator's direct path (as in Update)

Allow server to cache the roster / tree

Currently, clients are expected to cache the entire roster and tree (of size n and 2n-1, respectively), and the Welcome message provides these to the new joiner by value. In principle it's possible to create a scheme where:

  • The members of the group agree on a commitment to the roster / tree instead of the objects themselves
  • Each Handshake message includes the information necessary to update the commitment
  • ... and a proof of the signer's inclusion in the roster, relative to the current roster commitment

For example, if the roster were committed as a Merkle tree root, an Add message could come with (1) an inclusion proof for the signer's public key, relative to the prior tree root; and (2) a consistency proof between the prior tree root and the updated root.

This would open up a spectrum of options for how much state the clients have to cache (note that the client has to cache its direct path in any case, to be able to decrypt TreeKEM encryptions). The current draft would be on one end, with clients storing everything. The other end would have clients store nothing and handshake messages just carrying new entropy and updating commitments.

As an example of an intermediate state, if you assume that Updates are more common than Adds/Removes, you could require each client to cache its own copath. Then Add/Remove/Update messages would have to provide enough information about the tree to allow the other clients to update their copaths (in addition to updating the commitments).

Fix Terminology alignment

We need to discuss and agree on consistent definitions and terminology across documents.
I'll implement the changes for -02

Clarify obligation of clients to Update

It has been noted that we don't discuss enough he influence of clients refusing to update in this document. The architecture document briefly explain why we minimally should evict clients that refuse to update to preserve FS or PCS. I think we actually enforce a MUST and provide a minimal recommendation.

### Membership and offline members
Because Forward Secrecy (FS) and Post-Compromise Security (PCS)
rely on the deletion and replacement of keying material,
any client which is persistently offline
may still be holding old keying material and thus be a threat
to both FS and PCS if it is later compromised.
MLS does not inherently defend against this problem, but
MLS-using systems can enforce some mechanism for doing
so. Typically this will consist of evicting clients which
are idle for too long, thus containing the threat of
compromise. The precise details of such mechanisms are
a matter of local policy and beyond the scope of this document.

Fix issues introduced in #114

The PR from @kkohbrok introducing a KDF was merged before I had a chance to review it. There are a number of problems with it:

  • Instead of calling for an abstract KDF, it should define one, as we have with the use of HKDF elsewhere
  • We can't just say private_key = KDF(...), since KDFs produce octet strings, not private keys. We need Derive-Key-Pair(), not just Derive-Public-Key().
  • This doesn't match what I recall discussing on the list.

I think what you want is actually as follows:

path_secret[n+1]
     ^
     |
path_secret[n] --> node_secret --> node_key_pair

Or in prose:

node_secret = HKDF-Expand-Label(path_secret[n], "node", "", Hash.Length)
node_private, node_public = Derive-Key-Pair(node_secret)
path_secret[n+1] = HKDF-Expand-Label(path_secret[n], "path", "", Hash.Length)

Simplify nonce generation

Right now, nonces used to encrypt application messages are derived off the key schedule. Since the keys are effectively single-use, this could probably be done more simply, e.g., by using the generation number as the nonce.

Handshake message encryption

As proposed on the list, we should re-use the encrypted-message framing for encrypted handshake messages. For better key separation, we might derive a separate set of keys for this purpose (the academics prefer this).

If we do key separation, we should have a separate sequence number space. In any case, a type field will be needed to distinguish.

Discarding Application secrets from the previous Epoch

In the current draft it is not known to the other group members when to discard the participant application secret from the previous epoch. My formal specification sends the 4 byte application message counter of the previous epoch within the first application message of each participant in the new epoch. Discuss and PR.

Trivial DoS by a malicious client

At the end of the London meetup we discussed a potential problem: malicious clients can send a bad copath (e.g. just random group elements), which will totally screw up the group state of anyone who processes the update. This was not considered a valid attack in ART, which does not consider malicious clients or DoS, but is more of a problem here. In particular, one can imagine a group with the convention "invite anybody, delete people who misbehave" (e.g. like many IRC channels).

There are a few ways to handle this:

  • Ignore it: if you add someone malicious and they screw up your group state, well, you shouldn't have done that.
  • Wait for confirmation: when you receive a copath, don't trust it until someone else from the other part of the tree has sent an update, proving that they know the new DH value.
  • Something else

Server-initiated removal

Long-term inactive users undermine the FS and PCS properties of the protocol. Obviously, users can remove each other if they notice that a participant is inactive. We should consider whether we want to allow the server to do such a removal.

Application Secret deletion

It has been pointed out that the text is not clear enough about the fact that once the Application secrets of the senders have been computed, the shared Application secret MUST be deleted. Make that clear.

Weekly Digest (19 May, 2019 - 26 May, 2019)

Here's the Weekly Digest for mlswg/mls-protocol:


ISSUES

Last week 5 issues were created.
Of these, 1 issues have been closed and 4 issues are still open.

OPEN ISSUES

๐Ÿ’š #173 Formatting: removed \_ where it was syntactically incorrect, by rozbb
๐Ÿ’š #172 DirectPathNode contains encrypted node secrets, not path secrets, by rozbb
๐Ÿ’š #171 Specify an Init message, by bifurcation
๐Ÿ’š #170 Confirmation and transcript improvements, by bifurcation

CLOSED ISSUES

โค๏ธ #169 Notion of virtual client when secrets are shared accross devices, by beurdouche


PULL REQUESTS

Last week, 9 pull requests were created, updated or merged.

OPEN PULL REQUEST

Last week, 3 pull requests were opened.
๐Ÿ’š #173 Formatting: removed \_ where it was syntactically incorrect, by rozbb
๐Ÿ’š #172 DirectPathNode contains encrypted node secrets, not path secrets, by rozbb
๐Ÿ’š #171 Specify an Init message, by bifurcation

UPDATED PULL REQUEST

Last week, 1 pull request was updated.
๐Ÿ’› #170 Confirmation and transcript improvements, by bifurcation

MERGED PULL REQUEST

Last week, 5 pull requests were merged.
๐Ÿ’œ #169 Notion of virtual client when secrets are shared accross devices, by beurdouche
๐Ÿ’œ #167 Fix incorrect definition of update_secret, by beurdouche
๐Ÿ’œ #166 GroupState is not a group state, renaming to GroupContext, by beurdouche
๐Ÿ’œ #164 Rename UserInitKey to ClientInitKey, by beurdouche
๐Ÿ’œ #163 Reorder blanking and update in the Remove operation, by beurdouche


COMMITS

Last week there were 8 commits.
๐Ÿ› ๏ธ Merge pull request #164 from mlswg/beurdouche_clientinitkey Rename UserInitKey to ClientInitKey by bifurcation
๐Ÿ› ๏ธ Merge branch 'master' into beurdouche_clientinitkey by bifurcation
๐Ÿ› ๏ธ Merge pull request #163 from mlswg/beurdouche_remove Reorder blanking and update in the Remove operation by bifurcation
๐Ÿ› ๏ธ Remove: truncate the tree on sending by beurdouche
๐Ÿ› ๏ธ Fix merge conflict with master by beurdouche
๐Ÿ› ๏ธ [GroupState is not a group state, renaming to GroupContext (#166) * GroupState is not a group state, renaming to GroupContext


CONTRIBUTORS

Last week there were 2 contributors.
๐Ÿ‘ค bifurcation
๐Ÿ‘ค beurdouche


STARGAZERS

Last week there was 1 stargazer.
โญ eknoes
You are the star! ๐ŸŒŸ


RELEASES

Last week there were no releases.


That's all for last week, please ๐Ÿ‘€ Watch and โญ Star the repository mlswg/mls-protocol to receive next weekly updates. ๐Ÿ˜ƒ

You can also view all Weekly Digests by clicking here.

Your Weekly Digest bot. ๐Ÿ“†

User-Initiated Add

Currently, in order for a new member to join a group, an existing member needs to add them to the group. Certain use cases work more naturally if a new joiner can initiate the add process. I think that broadly speaking we want a process here where someone outside the group can (1) request to be added and (2) send to the group, but cannot receive from the group until added.

Some things to consider here:

  • Anything that is revealed to a joiner that joins this way is effectively public. Should they be able to see, e.g., the roster?

  • How should these interactions relate to the key schedule? Assuming there's some AddRequest message, should it be included into the transcript at Add time?

  • What happens if there are multiple parallel requests?

Possible typo in diagram?

Please correct me if my understanding is wrong:

  • The diagram of "user-initiated join" shows UserAdd(.->D) and state.add(D) initiated by user Z. Isn't it UserAdd(.->Z) and state.add(Z)?
  • The diagram of Update shows Update(A) message from server telling A and B to state.upd(D) and Z to state.upd(A). Shouldn't all of them be state.upd(A), because A initiated the update?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.