diff --git a/src/SUMMARY.md b/src/SUMMARY.md index c95dd76..f95842c 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -5,9 +5,12 @@ - [Open Questions](./open-questions.md) - [Connectivity](./connectivity.md) - [Tapir](./tapir.md) + - [Packet Format](./packet_format.md)md + - [Authentication Protocol](./authentication_protocol.md) - [Cwtch Library](./cwtch.md) - [Groups](./groups.md) - [Cwtch UI](./ui.md) + - [Profile Encryption & Storage](./profile_encryption_and_storage.md) - [Cwtch Server](./server.md) - [Development](./development.md) - [Deployment](./deployment.md) diff --git a/src/authentication_protocol.md b/src/authentication_protocol.md new file mode 100644 index 0000000..a77429f --- /dev/null +++ b/src/authentication_protocol.md @@ -0,0 +1,51 @@ +# Authentication Protocol + +Each peer, given an open connection \\(C\\): + +\\[ \\ +I = \mathrm{InitializeIdentity()} \\\\ +I_e = \mathrm{InitializeEphemeralIdentity()} \\\\ +\\\\ +I,I_e \rightarrow C \\\\ +P,P_e \leftarrow C \\\\ +\\\\ +k = \mathrm{KDF}({P_e}^{i} + {P}^{i_e} + {P_e}^{i_e}) \\\\ +c = \mathrm{E}(k, transcript.Commit()) \\\\ +c \rightarrow C \\\\ +c_p \leftarrow C \\\\ +\mathrm{D}(k, c_p) \stackrel{?}{=} transcript.LatestCommit() \\\\ +\\] + +The above represents a sketch protocol, in reality there are a few + implementation details worth pointing out: + +Once derived from the key derivation function \\(\mathrm{KDF}\\\) the key + \\(k\\) is set *on* the connection, meaning the authentication app doesn't + do the encryption or decryption explicitly. + +Also the concatenation of parts of the 3DH exchange is strictly ordered: + +* DH of the Long term identity of the outbound connection by the ephemeral + key of the inbound connection. +* DH of the Long term identity of the inbound connection by the ephemeral +key of the outbound connection. +* DH of the two ephemeral identities of the inbound and outbound connections. + +This strict ordering ensures both sides of the connection derive the *same* +session key. + +### Cryptographic Properties + +During an online-session, all messages encrypted with the session key can be authenticated by the peers as having come +from their peer (or at least, someone with possession of their peers secret key as it related to their onion address). + +Once the session has ended, a transcript containing the long term and ephemeral public keys, a derived session key and +all encrypted messages in the session cannot be proven to be authentic i.e. this protocol provides message & participant +repudiation (offline deniable) in addition to message unlinkability (offline deniable) in the case where someone is satisfied +that a single message in the transcript must have originated from a peer, there is no way of linking any other message to +the session. + +Intuition for the above: the only cryptographic material related to the transcript is the derived session key - if the +session key is made public it can be used to forge new messages in the transcript - and as such, any standalone +transcript is subject to forgery and thus cannot be used to cryptographically tie a peer to a conversation. + diff --git a/src/packet_format.md b/src/packet_format.md new file mode 100644 index 0000000..9ba91f8 --- /dev/null +++ b/src/packet_format.md @@ -0,0 +1,12 @@ +# Packet Format + +All tapir packets are fixed length (8192 bytes) with the first 2 bytes indicated the actual length of the message, +`len` bytes of data, and the rest zero padded: + + | len (2 bytes) | data (len bytes) | paddding (8190-len bytes)| + +Once encrypted, the entire 8192 byte data packet is encrypted using [libsodium secretbox](https://libsodium.gitbook.io/doc/secret-key_cryptography/secretbox) using the standard structure ( +note in this case the actual usable size of the data packet is 8190-14 to accommodate the nonce included by secret box) + +For information on how th secret key is derived see the [authentication protocol](./authentication_protocol.md) + diff --git a/src/profile_encryption_and_storage.md b/src/profile_encryption_and_storage.md new file mode 100644 index 0000000..c06e49b --- /dev/null +++ b/src/profile_encryption_and_storage.md @@ -0,0 +1,20 @@ +# Profile Encryption & Storage + +Profiles are stored on locally on disk and encrypted using a key derived from user-known password (via pbkdf2). + +Note that once encrypted and stored on disk, the only way to recover a profile is by rederiving the password - as such +it isn't possible to provide a full list of profiles a user might have access to until they enter a password. + +## Unencrypted Profiles and the Default Password + +To handle profiles that are "unencrypted" (i.e don't require a password to open) we currently create a profile +with a [default, hardcoded password](https://git.openprivacy.ca/cwtch.im/ui/src/branch/master/go/the/globals.go#L12). + +This isn't ideal, we would much rather wish to rely on OS-provided key material such that the profile is bound to a +specific device, but such features are currently patchwork - we also note by creating an unencrypted profile, people +who use Cwtch are explicitly opting into the risk that someone with access to the file system may be able to decrypt +their profile. + +### Related Code + +https://git.openprivacy.ca/cwtch.im/cwtch/src/commit/3529e21b0e0763ca6ec20ddfd13e22c8070c4915/storage/v1/file_enc.go diff --git a/src/risk.md b/src/risk.md index 769529f..9bc83c3 100644 --- a/src/risk.md +++ b/src/risk.md @@ -56,6 +56,28 @@ Beyond individual conversations, we also seek to defend against context correlat predictable. E.g. Alice calls Eve every Monday evening for around an hour. +### Active Attacks + +#### Misrepresentation Attacks + +Cwtch provides no global display name registry, and as such people using Cwtch are more vulnerable to attacks +based around misrepresentation i.e. people pretending to be other people: + +A basic flow of one of these attacks is as follows, although other flows also exist: + +- Alice has a friend named Bob and another called Eve +- Eve finds out Alice has a friend named Bob +- Eve creates thousands of new accounts to find one that has a similar picture / public key to Bob (won't be identical but might fool someone for a few minutes) +- Eve calls this new account "Eve New Account" and adds Alice as a friend. +- Eve then changes her name on "Eve New Account" to "Bob" +- Alice sends messages intended for "Bob" to Eve's fake Bob account + +Because misrepresentation attacks are inherently about trust and verification the only absolute way of preventing them +is for users to absolutely validate the public key. This is obviously not-ideal and in many cases simply *won't-happen*. + +As such we aim to provide some user-experiance hints in the [ui](./ui.md) to guide people in making choices around whether +to trust accounts and/or to distinguish accounts that may be attempting to represent themselves as other users. + ## A note on Physical Attacks Cwtch does not consider attacks that require physical access (or equivalent) to diff --git a/src/tapir.md b/src/tapir.md index c14ede3..fa58293 100644 --- a/src/tapir.md +++ b/src/tapir.md @@ -48,42 +48,10 @@ Initializes a [Merlin](https://merlin.cool)-based cryptographic transcript that * **Capabilities Granted**: *AuthenticationCapability* * **Capabilities Required**: *None* -Engages in an ephemeral triple-diffie-hellman handshake to derive a unique, +Engages in an [ephemeral triple-diffie-hellman handshake](./authentication_protocol.md) to derive a unique, authenticated session key. -Each peer, given an open connection \\(C\\): -\\[ \\ -I = \mathrm{InitializeIdentity()} \\\\ -I_e = \mathrm{InitializeEphemeralIdentity()} \\\\ -\\\\ -I,I_e \rightarrow C \\\\ -P,P_e \leftarrow C \\\\ -\\\\ -k = \mathrm{KDF}({P_e}^{i} + {P}^{i_e} + {P_e}^{i_e}) \\\\ -c = \mathrm{E}(k, transcript.Commit()) \\\\ -c \rightarrow C \\\\ -c_p \leftarrow C \\\\ -\mathrm{D}(k, c_p) \stackrel{?}{=} transcript.LatestCommit() \\\\ -\\] - -The above represents a sketch protocol, in reality there are a few - implementation details worth pointing out: - -Once derived from the key deriviation function \\(\mathrm{KDF}\\\) the key - \\(k\\) is set *on* the connection, meaning the authentication app doesn't - do the encryption or decryption explicitly. - -Also the concatenation of parts of the 3DH exchange is strictly ordered: - -* DH of the Long term identity of the outbound connection by the ephemeral - key of the inbound connection. -* DH of the Long term identity of the inbound connection by the ephemeral -key of the outbound connection. -* DH of the two ephemeral identities of the inbound and outbound connections. - -This strict ordering ensures both sides of the connection derive the *same* -session key. ### transcript.Commit()