forked from cwtch.im/cwtch
142 lines
5.2 KiB
Markdown
142 lines
5.2 KiB
Markdown
|
Title: Cwtch Protocol: Facilitating Anonymous Collaboration
|
||
|
Author: Sarah Jamie Lewis
|
||
|
Doc Class : [11pt, twocolumn]article
|
||
|
|
||
|
# Actors & Identity
|
||
|
|
||
|
All parties in a Cwtch System run ricochet nodes.
|
||
|
|
||
|
## Cwtch Client
|
||
|
|
||
|
A Cwtch Client identity consists of:
|
||
|
|
||
|
* A Name
|
||
|
* An Onion Address (and an associated private key)
|
||
|
* A Nacl Public Key (and an associated private key)
|
||
|
|
||
|
## Cwtch Server
|
||
|
|
||
|
A Cwtch Server identity consists of:
|
||
|
|
||
|
* A Name
|
||
|
* An Onion Address (and an associated private key)
|
||
|
|
||
|
# Threat Model
|
||
|
|
||
|
## Impersonation
|
||
|
|
||
|
One of the key attacks we must defend against in a multiple-party messaging
|
||
|
system is the risk of one party attempting to impersonate another.
|
||
|
|
||
|
There are two levels to this kind of the attack, systemic impersonation and superficial
|
||
|
impersonation.
|
||
|
|
||
|
Systemic Impersonation would result from the system being unable to distinguish between
|
||
|
two parties. Due to the anonymous nature of our approach, we adopt a long lived public key
|
||
|
that can be used to link & verify that seperate messages belong to the same party.
|
||
|
|
||
|
Superficial Impersonation is more tricky, it would result from a user being tricked to accepting
|
||
|
that two distinct identities are the same. We cannot rely on the user to compare public keys to avoid
|
||
|
this. An attacker may try and change their profile name to match a target - it should be noted that restricting profile names to be unique per Cwtch system is not sufficient to prevent this attack (because of homoglyph style attacks), nor is such a restriction desirable.
|
||
|
|
||
|
To prevent superficial style impersonation we take a multi step approach:
|
||
|
|
||
|
// TODO
|
||
|
|
||
|
# Client <-> Server Messages
|
||
|
|
||
|
When a client wishes to join a Cwtch system, they must first identify the address of the Cwtch server.
|
||
|
|
||
|
One a Cwtch server is known, the client connects to the Cwtch server over Ricochet, and performs a standard `im.ricochet.auth.hidden-service` authentication.
|
||
|
|
||
|
At this point the Cwtch Server initiates an `EnableFeatures` setup in an attempt to detect that the client is indeed a Cwtch client, or if it is a bare bones Ricochet client.
|
||
|
|
||
|
message ServerIdentify {
|
||
|
string name = 1;
|
||
|
string topic = 2;
|
||
|
int32 difficulty = 3;
|
||
|
}
|
||
|
|
||
|
If a Cwtch Client is detected, that the CwtchServer sets up a `im.cwtch.event` through which all other communication between the client and the server takes place.
|
||
|
|
||
|
enum EventType {
|
||
|
NIL = 0;
|
||
|
JOIN = 1;
|
||
|
LEAVE = 2;
|
||
|
MESSAGE = 3;
|
||
|
}
|
||
|
|
||
|
message Event {
|
||
|
EventType type = 1;
|
||
|
string client = 2;
|
||
|
int64 timestamp = 3;
|
||
|
string detail = 4;
|
||
|
bytes proof = 5;
|
||
|
}
|
||
|
|
||
|
## Event Types
|
||
|
|
||
|
* *JOIN* events are sent when a client connects to the server
|
||
|
* *LEAVE* events are sent when a client disconnects from the server
|
||
|
* *MESSAGE* events are sent when a client sends a message to the server, these are broadcast to every other connected client.
|
||
|
|
||
|
## Sending Messages
|
||
|
|
||
|
message Message {
|
||
|
string message = 1;
|
||
|
bytes signature = 2;
|
||
|
bytes spamguard = 3;
|
||
|
}
|
||
|
|
||
|
## Message Signatures
|
||
|
|
||
|
|
||
|
|
||
|
### Preventing Spam Through SpamGuard
|
||
|
|
||
|
To prevent abusive clients from flooding the server (and therefore other clients) with
|
||
|
a large number of message, all messages must include a complet `spamguard` field.
|
||
|
|
||
|
This field is `nonce|sha256(message.signature.nonce)`. Valid spamguard fields must
|
||
|
ensure that the sha256 digest begins with `difficulty` number of `0x00` as defined
|
||
|
by the server profile.
|
||
|
|
||
|
This requires that clients try a number of random nonces prior to sending any messages.
|
||
|
|
||
|
Message packaets with invalid SpamGuard digests will be discarded by the server.
|
||
|
|
||
|
To ensure that a client cannot find a single valid SpamGuard digest, e.g. for the message `hi`,
|
||
|
and use that to spam clients.
|
||
|
|
||
|
|
||
|
# Client <-> Client Messages
|
||
|
|
||
|
## ClientIdentify
|
||
|
|
||
|
When 2 clients are online at the same time, they can use the opporunity to exchange
|
||
|
`ClientIdentify` messages over an `im.cwtch.client.identify` channel:
|
||
|
|
||
|
message ClientIdentify {
|
||
|
string name = 1;
|
||
|
bytes ed25519_public_key = 2;
|
||
|
bytes nacl_public_key = 3;
|
||
|
}
|
||
|
|
||
|
* `name` is a readable name to help identify this client.
|
||
|
* `ed25519_public_key `is used to authenticate public messages from this client.
|
||
|
* `nacl_public_key` is used to authenticate private messages from this client.
|
||
|
|
||
|
Once a client has the Profile of another client, they can proceed to validate that
|
||
|
the messages they have received from the server via the `im.cwtch.event` that are tagged
|
||
|
as originating from the client do in fact validate.
|
||
|
|
||
|
## Private Messages
|
||
|
|
||
|
When both clients are online, private messages can be sent to eachother using an
|
||
|
`im.ricochet.chat` channel.
|
||
|
|
||
|
When either client is offline, private messages are sent utilizing the `im.cwtch.message` channel - instead of a regular message being sent, the message is begins `ENC-` and contains an encrypted message.
|
||
|
|
||
|
Note that there is no metadata associated with private messages, and as such each client must attempt to decrypt the message with their own keys, and discard messages that fail.
|
||
|
|