-
Notifications
You must be signed in to change notification settings - Fork 3
WakuChat Protocol #73
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
Draft
jazzz
wants to merge
3
commits into
master
Choose a base branch
from
jazzz/wakuchat
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,172 @@ | ||
| --- | ||
| title: WakuChat | ||
| name: A private decentralized messaging protocol for multiple usecases. | ||
| category: Standards Track | ||
| status: raw | ||
| tags: chat | ||
| editor: Jazz Alyxzander<[email protected]> | ||
| contributors: | ||
| --- | ||
| # Abstract | ||
|
|
||
| This specification defines a modular communication protocol designed to provide a privacy focused approach to common messaging patterns. The protocol employs a lean root layer that defers to independent sub-protocols for defining communication behavior, with versioning as a first-class concept for handling protocol evolution. | ||
|
|
||
| # Background / Rationale / Motivation | ||
|
|
||
| Traditionally communication protocols face several critical challenges as they grow. | ||
|
|
||
| Different communication scenarios have vastly different requirements. A protocol optimized for high-volume public broadcasts performs poorly for intimate encrypted conversations, and vice versa. Monolithic protocols cannot optimize for these diverse use cases simultaneously. | ||
|
|
||
| Once widely deployed, communication protocols become difficult to modify. Even minor changes can break compatibility across clients. As a result versioning becomes a complex negotiation problem, which makes deploying protocol updates difficult. At each stage protocols become increasingly difficult to modify, which slows down forward progress and eventually leads to ossification. | ||
|
|
||
| What is desired is integral protocol resiliency by embedding a versioning strategy from the beginning. | ||
|
|
||
| # Theory / Semantics | ||
|
|
||
| This protocol is a lean orchestration framework which provides the backbone for smaller independent "Conversation" sub-protocols. Conversation protocols completely define a communication channel. This root protocol provides common functionality to support a wide array of communication use cases, and the remaining functionality is deferred to Conversation protocols to define. | ||
|
|
||
| This specification outlines how clients can initiate messages with one another, determine how to decode/decrypt incoming messages and support a wide range of communication patterns. | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram | ||
| actor S as Saro | ||
| participant SI as Saro DefaultInbox | ||
| participant C as Convo | ||
| participant RI as Raya DefaultInbox | ||
| actor R as Raya | ||
|
|
||
|
|
||
| Note over SI,RI: All clients subscribe to their default Inbox | ||
|
|
||
| SI ->> S: Subscribe | ||
| RI ->> R: Subscribe | ||
|
|
||
| Note over R: Key Information is exchanged OOB | ||
|
|
||
| Note over S: Conversation is created | ||
| C ->> S : Subscribe | ||
| S ->> RI : Send Invite `I1` | ||
| S ->> C : Send Message `M1` | ||
|
|
||
| RI --) R : Recv `I1` | ||
| Note over R: Conversation is joined | ||
| C ->> R : Subscribe | ||
| C --) R: Recv `M1` | ||
|
|
||
| R ->> C: Send M2 | ||
| C --) S: Recv M2 | ||
| ``` | ||
|
|
||
|
|
||
| ## Conversations | ||
| ConversationTypes are standalone methods to send and receive messages. While a full service "chat" protocol needs to provide additional features such as identity management, message history, backups and versioning, conversations are more narrowly scoped. | ||
|
|
||
| They can be created permissionlessly within the WakuChat Protocol, as there is no required registration. Developers are free to use any given conversation type as long as all intended participants support it. | ||
|
|
||
|
|
||
|
|
||
| ConversationTypes MUST implement the [Conversations](./conversations.md) specification in order to maintain compatibility. | ||
|
|
||
|
|
||
| ## Versioning Strategy | ||
|
|
||
| Versioning is one of the hardest problems in decentralized messaging. Keeping a network of decentralized applications and clients up-to-date and version compatible requires careful planning and orchestration. WakuChat's approach to versioning is avoid these problems by removing the issue. | ||
|
|
||
| In WakuChat incompatible versions of a conversation protocol result in distinct conversationTypes (E.g. PrivateV1 vs PrivateV3). That is; breaking changes are not distinguished by client version, but by ConversationType. This opinionated approach has some interesting outcomes: | ||
|
|
||
| - Compatibility is not determined by the version of a client, but rather by which types the participants supported. | ||
| This removes the requirement for all clients to be running the same version, which allows faster roll out of features. Fine grained negotiation of supported types embraces the decentralized nature of the clients and avoids headaches of keeping clients in lockstep. | ||
|
|
||
| - Upgrading to a new ConversationType is equivalent to negotiating a new Conversation and cleaning up the old one. | ||
| This reuses the existing conversation initiation mechanism, which reduces complexity. | ||
|
|
||
| - Forces a decoupling between User-level-conversations and the conversationTypes which provide transport. This makes it easier to roll out changes. | ||
|
|
||
| Individual conversationTypes can implement functionality to migrate participants to a conversation, but that is deferred to contributors. Individual conversationType are free to choose an upgrade plan that makes sense for their usecases. | ||
|
|
||
|
|
||
| ## Default Inbox | ||
| There exists a circular dependency in initializing a Conversation. Conversations require an established conversation to send an invitation, yet at the beginning no channel exists between contacts. | ||
|
|
||
| To resolve this all clients MUST implement a default [Inbox](./inbox.md) to receive initial messages. The default inbox allows clients to discover new conversations asynchronously without prior coordination. By listening in a static location know to senders, clients can always receive new invitations. | ||
|
|
||
| The default inbox MUST be configured with the parameters: | ||
| - **inbox_addr:** `client_address` | ||
|
|
||
| One important property of the Inbox is that it can receive different payload types in a single location, by decoupling payload type from the associated contact_topic. New Conversation types will invariably create new payload types. Multiplexing payload types into a single inbox means the default inbox can be reused for undefined future conversationTypes. | ||
|
|
||
| The Default Inbox having public visibility does not preclude Clients having other Inboxes with different levels of visibility. | ||
|
|
||
| As the clients address is directly linked to Default Inbox, this pathway SHOULD only be used as a last resort. | ||
|
|
||
|
|
||
| ## Envelopes | ||
| As clients can support multiple sub-protocols simultaneously, a mechanism is required to determine how decode payloads. | ||
|
|
||
| To process a payload, a client must know how a payload was encoded/encrypted and what encryption state to use to decrypt it. | ||
|
|
||
| **Encoding** | ||
| One approach to tracking payload types is to encode it in the content topic. | ||
| Clients can then infer how to decode the payload, based on where it was received. | ||
| The downside is that only one type of payload can be received in a content topic. | ||
| Deploying new types requires a new content topic, which may go unnoticed to clients if they are running an older version or do not support the protocol. | ||
| Even if the client cannot read the payload, knowing it exists can signal to developers a need to update their applications to support the new types; reducing interaction failure and catching errors. | ||
|
|
||
| **Encryption State** | ||
| To determine which encryption state to use in decryption, applications must attach identifying information. One method to achieve this and ensure privacy, is shield the required identifying information from public view using asymmetric encryption. However double encryption is expensive, and more opportunity for security faults. | ||
|
|
||
|
|
||
| ### Conversation Hinting | ||
|
|
||
| Conversation hinting is a mechanism to provide recipients with the necessary information, without exposing conversational metadata. | ||
|
|
||
| Naively, conversation_ids are sufficient to allow clients to determine how to decrypt a payload. As the conversation_id corresponds to the ConversationType which defines how payloads are encdoded, and the encryption state is linked to the specific identifier. However this would leak Conversation metadata, as observers could determine which payloads belonged together into a group. Instead a hint is used which allows clients to check if this payload is of interest. A ConversationHint does not contain identifying information. | ||
|
|
||
| ConversationHints are computed by using a salted hash of the `conversationId`. specifically defined as `lowercase_hex(blake2s(salt || conversation_id))`. | ||
|
|
||
| Clients can check if a conversation_hint is of interest to them, then retrieve the associated encryption state. Payloads with an unknown hint can be safely disregarded. | ||
|
|
||
|
|
||
| ## Wire Format Specification / Syntax | ||
|
|
||
| The wire format is specified using protocol buffers v3. | ||
|
|
||
| ```protobuf | ||
|
|
||
| message WapEnvelopeV1 { | ||
|
|
||
| // Indicates which conversation this message belongs to without revealing metadata | ||
| string conversation_hint = 1; | ||
| // Used to compute the conversation_hint | ||
| uint32 salt = 2; | ||
| // Data encoded according to the corresponding ConversationType | ||
| bytes payload = 3; | ||
| } | ||
|
|
||
| ``` | ||
|
|
||
| ## Implementation Suggestions (optional) | ||
|
|
||
| ### Application Interop | ||
|
|
||
| Developers wishing to interop with other projects will need to ensure they have overlapping support of ConversationTypes. | ||
|
|
||
| ### User level Conversations | ||
|
|
||
| Application developers should maintain standalone identifiers for user-level conversations that are separate from the protocol-level conversation_id. A single logical conversation from the user's perspective may utilize multiple ConversationTypes over time. As versions are considered different types, the underlying relationship is many to one. By maintaining application-level conversation identifiers, developers can provide users with consistent conversation continuity while the underlying protocol mechanisms handle version transitions and security upgrades transparently. | ||
|
|
||
|
|
||
| ## Security/Privacy Considerations | ||
|
|
||
| Payloads inherit the privacy and security properties of the ConversationType used to send them. Please refer to the corresponding specifications when analyzing properties. | ||
|
|
||
| ### Default Inbox Privacy | ||
| Payloads sent to the default inbox are linkable to an client (as it is derived from the clients address). This means that if a target client address is known to an observer, they can determine if any payloads were sent to the target using the default inbox. In this case the Envelopes contain no sender information, so this does not leak social graph information. | ||
|
|
||
| ## Copyright | ||
|
|
||
| Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). | ||
|
|
||
| ## References | ||
|
|
||
| A list of references. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This approach to hinting offers insufficient privacy protections. A strategy using either SealedSender or Ratcheting Private Identifiers would be better suited.