Negotiated topics
| Created | Author(s) | Status |
|---|---|---|
| 2022-08-22 | @mkobetic | Draft |
Goals
- Conversation topics are negotiated using an intro message in privacy preserving manner.
- There is no un-encrypted identifying information present in conversation messages
Questions
- What is the topic structure for the various meta-messages? one big meta-topic, many dedicated topics?
- Without the key identifier present in the message header, how is the pre-key for decryption determined? Try all known keys? A key index? ...
Current situation
Conversations
Topics
Conversations are initiated by sending a message to 3 different topics:
- sender's intro-topic -
intro-walletA - recipient's intro-topic -
intro-walletB - conversation topic -
dm-walletA-walletB
Following messages are sent to the conversation topic only. There can be multiple introductory messages from the same sender in a recipient's intro topic. All future conversations will go into the same conversation topic as it is strictly tied to participants' wallet addresses.
Messages
Conversation messages include a plain text header identifying the sender's and recipient's public key bundle used to encrypt the message. The header aids decryption by either party. The payload is encrypted.
Meta-messages
PublicKeyBundles - contacts
Participants advertise their public key bundles in a contact topic, contact-walletAddress. Messages in these topics are PublicKeyBundles, carrying unencrypted public identity key and public pre-key of the wallet. The key bundle is generally republished on every client startup. Clients are expected to ignore all but the latest bundle.
PrivateKeyBundles - private storage
Participant's publish encrypted private key bundles into their private storage topic, privatestore-walletAddress. This allows clients to bootstrap themselves with pre-existing keys. Messages in these topics are PrivateKeyBundles, carrying encrypted private identity key and private pre-keys of the wallet. The bundle is usually published only once, although it could be republished if we want to add new or rotate existing keys. Clients should ignore all but the latest bundle.
Proposed changes
Invite topics
Replace the intro topics with invite topics. Messages in the invite topics will carry an invitation from the initiator of the conversation which will include:
randomly generated topic name that will be used for the conversation
- make sure the name is sufficiently large to make the topic space sufficiently sparse so that it is hard to randomly guess topics (32 bytes?).
- the name MUST be generated with sufficient randomness to make name collisions with other invitations highly improbable
randomly generated bytes (32?) used as the key material for encryption of messages in this conversation
The invitation message is encrypted using the X3DH scheme we use for messages currently (see Key Passing RFC #662 for details).
The initiator still sends the invitation to their own invite topic as well to have a record of the the topic and key material. The invitation message would be identical, i.e. the sender is still the initiator, which can be useful to distinguish own invitations from others.
Conversation Topics
Topic name is determined by the invitation that initiated it. Messages in the topic will omit the sender/recipient pub key bundles from the message header. The payload is encrypted using the scheme indicated by the invitation (e.g. AES256-GCM-HKDF-SHA256). The key material from the invitation is used as the input into the scheme's key derivation function (e.g. HKDF).
The omitted sender header is replaced with a new SignedContent wrapper that will embed EncodedContent and will be encrypted inside Ciphertext.payload.
message SignedContent {
bytes content = 1; // contains EncodedContent
PublicKeyBundle sender = 2;
Signature signature = 3;
}
The signature signs a digest of concatenated message timestamp, topic name and the content bytes (the specifics of this concatenation will be worked out at implementation time) using the sender's pre-key.
Analysis
Security
Authentication: stems transitively from authenticity of the invitation. Only parties that know the contents of the invitation know the topic and the key material. If the invitation is authentic, the messages can be assumed to be authentic as well (as long as the authenticated decryption succeeds). In a group setting that means that a recipient can only be sure that a member of the group authored a message, but not sure which member exactly. This keeps the messages deniable at the cost of authentication strength. Strengthening authentication would require signing individual messages (presumably with identity keys) which will remove deniability. See Question: Sender deniability in xmtp:channels for more discussion on this.
Deniability: is eliminated in favor of signed messages, to support group communication and signed 1:1 communication use-cases. Optional signing was rejected at this point due to lack of motivating use-cases and to keep the protocol simpler.
Privacy: the initiator picks the key material, but the invitee can mix in additional input through KDF salt or encryption nonce. I think it should result largely in the same level of privacy as before. It may make sense for the invitee to scrutinize the invitation for sufficient randomness, although it may not be worth it beyond some very trivial testing. Even if the key material is all zeros, properly random KDF salt should mitigate that.
Unobservability: The conversation messages no longer leak any participant identifiers (goal). The invitation messages still do so Eve can still create a graph of invitations between wallets, but cannot say whether any actual communication happened. The conversation topics are completely random, so no way to relate that to the participants other than observing contact points with the network. Assuming topic names are sufficiently large, it may also be prohibitively difficult to find a random topic just by guessing topic names (barring broken clients with bad topic generation).
There is likely some benefit from not using X3DH keys for conversations, thus significantly reducing the amount of material for cryptanalysis. However private key compromise still compromises all conversations initiated under that key.
Backward compatibility
This proposal allows 1:1 conversations just as before with the caveat that the participants can no longer be sure that they are in a 1:1 conversation. It also opens the possibility of multiple parties communicating over the same topic simply by having the initiator send the same invitation to multiple invitees. There really isn't any distinction between 1:1 and group conversations other than the number of participants.
This proposal enables parties to create new topics for new conversations. This is desirable from security POV, but can put a lot more strain on the client depending on what kind of conversation view it wants to present. E.g. our example chat app may need to recombine multiple conversations to get the unified 1:1 conversation view. This is a trade-off and we should find the right balance between re-using topics forever and changing them all-the-time.
Dedicated, pre-determined invite topics make it simple to find all invitations relevant to a participant without having to search through a large topic or multiple topics. Separating the invite topics from the old intro topics avoids having to detect type of messages received and acting differently. There can be two separate streams of invites, one from the old intro messages (the topic and key material is deterministic) and one from the new invitation messages that can then be combined into a single stream of invitations that can be processed uniformly.
The proposal clearly separates old and new style conversation topics, so even though we have a self describing scheme for messages in place, we could take advantage of the topic distinction too.
There is no need to indicate public key used on the conversation messages, the key material from the invitation is static.
Message sender and signature handling will have to adjust depending on which version of message is being processed.