# P2P Messaging with Encryption
### Libraries
- x_salsa20_poly1305
- create_x25519_keypair
- x_25519_x_salsa20_poly1305_encrypt
- x_25519_x_salsa20_poly1305_decrypt
### Structures
```rust
pub struct IdentityKey {
agent: AgentPubKey,
key: X25519PubKey,
}
pub struct P2PMessage {
author: AgentPubKey,
receiver: AgentPubKey,
payload: Payload,
time_sent: Timestamp,
reply_to: Option<EntryHash>,
}
pub struct EncryptedP2PMessage {
sender: AgentPubKey,
recipient: AgentPubKey,
hash: EntryHash,
data: XSalsa20Poly1305EncryptedData
}
```
- **sender** and **recipient**
- used in getting the associated encrypting/decrypting keys from lair
- having them in plaintext may expose the social graph to attackers
- **hash**:
- represents the hash of the actual `P2PMessage`
- allows for conditional checks without decrypting the message first
- can we rely on the hash of the encrypted entry?
- **key**:
- X25519PubKey used in encryption (as opposed to AgentPubKeys used in signing)
### Functions
#### init()
- creates a x25519 keypair (public and private)
- commits an `IdentityKey` entry in the DHT (public entry)
- links the `IdentityKey` entry to the agent's pubkey
- allows other agents to get a hold of your public encrypting key when they want to send you a message
```mermaid
sequenceDiagram
participant ACC as Alice_Conversation_Cell
participant DHT as DHT
ACC-->>ACC: call `init`
ACC-->>ACC: call create_x25519_keypair
ACC-->>DHT: create_entry IdentityKey containing the Public Encrypting Key
ACC-->>DHT: create_link from agent's AgentPubKey to IdentityKey
```
#### get_agent_key(agent: AgentPubKey) -> ExternResult\<IdentityKey>
```rust
pub struct IdentityKey {
agent: AgentPubKey,
key: X25519PubKey,
}
```
```mermaid
sequenceDiagram
participant fn as caller_fn
participant ACC as Alice_Conversation_Cell
participant DHT as DHT
fn-->>ACC: call `get_agent_key` with an agent's PubKey as input
ACC-->>DHT: get_links on AgentPubKey with tag "identity_key"
DHT-->>ACC: return links
ACC-->>DHT: get_details on link target
DHT-->>ACC: return details
ACC-->>ACC: convert details to IdentityKey entry
ACC-->>fn: return IdentityKey
```
#### encrypt(input: EncryptInput) -> ExternResult\<XSalsa20Poly1305EncryptedData>
```rust=
pub struct EncryptInput {
recipient: AgentPubKey,
data: XSalsa20Poly1305Data,
}
```
```mermaid
sequenceDiagram
participant fn as caller
participant ACC as Alice_Conversation_Cell
participant DHT as DHT
fn-->>ACC: call `encrypt`
ACC-->>DHT: call `get_agent_key` with the recipient AgentPubKey as input
DHT-->>ACC: return IdentityKey
note over ACC: can we do a query here instead?
ACC-->>DHT: call `get_agent_key` with the own AgentPubKey as input
DHT-->>ACC: return IdentityKey
ACC-->>ACC: call `x_25519_x_salsa20_poly1305_encrypt` with the returned X25519PubKeys
ACC-->>fn: return encrypted data
```
#### decrypt(input: DecryptInput) -> ExternResult\<XSalsa20Poly1305Data>
```rust=
pub struct EncryptInput {
sender: AgentPubKey,
data: XSalsa20Poly1305Data,
}
```
```mermaid
sequenceDiagram
participant fn as caller
participant ACC as Alice_Conversation_Cell
participant DHT as DHT
fn-->>ACC: call `decrypt`
ACC-->>DHT: call `get_agent_key` with the sender AgentPubKey as input
DHT-->>ACC: return IdentityKey
note over ACC: can we do a query here instead?
ACC-->>DHT: call `get_agent_key` with the own AgentPubKey as input
DHT-->>ACC: return IdentityKey
ACC-->>ACC: call `x_25519_x_salsa20_poly1305_decrypt` with the returned X25519PubKeys
ACC-->>fn: return decrypted data
```
#### Send a Message
```rust=
pub struct EncryptedP2PMessage {
sender: AgentPubKey,
recipient: AgentPubKey,
hash: EntryHash,
data: XSalsa20Poly1305EncryptedData
}
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACC as Alice_Conversation_Cell
participant DHT as DHT
participant BCC as Bobby_Conversation_Cell
participant BUI as Bobby_UI
AUI-->>ACC: call `send_message` with Bobby as receiver
ACC-->>ACC: construct P2PMessage Entry
ACC-->>ACC: get hash of P2PMessage Entry
rect rgba(200,0,0,0.5)
ACC-->>ACC: call `encrypt()` P2PMessage Entry
end
ACC-->>ACC: construct EncryptedP2PMessage Entry
ACC-->>ACC: commit EncryptedP2PMessage Entry to chain
ACC-->>AUI: return P2PMessage Entry
rect rgba(0,200,0,0.2)
note over ACC: post-commit
ACC-->>ACC: call `commit_message_to_receiver_chain()`
ACC-->>BCC: call_remote to receiver's `receive_message()`
BCC-->>BCC: commit EncryptedP2PMessage Entry to chain
BCC-->>BCC: create P2PMessageReceipt Entry
BCC-->>BCC: commit P2PMessageReceipt Entry to chain
rect rgba(200,0,0,0.5)
BCC-->>BCC: call `decrypt()` with EncryptedP2PMessage Entry as input
end
BCC-->>BUI: emit_signal containing the decrypted message
BCC-->>ACC: return Ok
end
rect rgba(0,200,0,0.2)
note over BCC: post-commit
BCC-->>BCC: call `commit_receipt_to_sender_chain()`
BCC-->>ACC: call_remote to sender's `receive_receipt()`
ACC-->>ACC: commit P2PMessageReceipt Entry to chain
ACC-->>AUI: emit_signal containing the receipt
ACC-->>BCC: return Ok
end
```
### query (General flow)
```rust=
pub struct P2PMessage {
author: AgentPubKey,
receiver: AgentPubKey,
payload: Payload,
time_sent: Timestamp,
reply_to: Option<EntryHash>,
}
pub struct EncryptedP2PMessage {
sender: AgentPubKey,
recipient: AgentPubKey,
hash: EntryHash,
data: XSalsa20Poly1305EncryptedData
}
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACC as Alice_Conversation_Cell
participant DHT as DHT
AUI-->>ACC: call `query`
ACC-->>ACC: query EncryptedP2PMessages entries from chain
loop for encrypted_message in query results
ACC-->>ACC: check for filtering conditions (author, receiver, hash)
alt message should be returned
ACC-->>ACC: call `decrypt()` on encrypted_message
ACC-->>ACC: check for time filtering conditions
alt message should be returned
ACC-->>ACC: process message and insert to hashmap
end
else message should not be returned
ACC-->>ACC: continue with loop
end
end
```
### Security Analysis and Comparison to the Signal Protocol
```mermaid
sequenceDiagram
participant UI as UI
participant WASM as WASM
participant Lair as Lair
participant Chain as Chain
participant WASM2 as WASM2
participant Chain2 as Chain2
UI-->>WASM: plaintext
WASM-->>Lair: plaintext
Lair-->>Lair: encrypt
Lair-->>WASM: encrypted
WASM-->>Chain: encrypted
WASM-->>WASM2: encrypted + encryption via `call_remote`
WASM2-->>Chain2: encryped
```
| | | Signal | Holochain | Comment |
|----------- |----------------------------------- |-------------------- |-------------------- |------------------------------------------------ |
| | Confidentiality | :heavy_check_mark: | :heavy_check_mark: | |
| | Integrity | :heavy_check_mark: | :x: | Need MACs or signatures. |
| | Authentication | :heavy_check_mark: | partial | |
| | Participant Consistency | :heavy_check_mark: | partial | Need MACs or signatures. |
| | Destination Validation | :heavy_check_mark: | partial | Need MACs or signatures. |
| | Forward Secrecy | :heavy_check_mark: | :x: | Single encrypting key for all messages |
| | Backward Secrecy/Self-Healing/PCS | :heavy_check_mark: | :x: | Single encrypting key for all messages |
| | Anonymity Preserving | | :x: | Encryption PubKeys are linked to AgentPubKeys |
| | Speaker Consistency | :heavy_check_mark: | | |
| | Causality Preserving | :heavy_check_mark: | | |
| | Global Transcript | | | |
| | Message Unlinkability | :heavy_check_mark: | :x: | Author and recipient agent keys are plaintext. |
| | Message Repudiation | :heavy_check_mark: | :x: | Author and recipient agent keys are plaintext. |
| | Participant Repudiation | :heavy_check_mark: | :x: | Author and recipient agent keys are plaintext. |
| Usability | Out-of-Order Resilient | :heavy_check_mark: | :heavy_check_mark: | Single encrypting key for all messages |
| Usability | Dropped Message Resilient | :heavy_check_mark: | :heavy_check_mark: | Single encrypting key for all messages |
| Usability | Asynchronicity | :heavy_check_mark: | partial | |
| Usability | Multi-Device Support | partial | partial | |
| Usability | No Additional Service | | TBD | No need for a key server aside from DHT. |
| Group | Computational Equality | :heavy_check_mark: | NA | |
| Group | Trust Equality | :heavy_check_mark: | NA | |
| Group | Subgroup Messaging | :heavy_check_mark: | NA | |
| Group | Contractable | :heavy_check_mark: | NA | |
| Group | Expandable | :heavy_check_mark: | NA | |
### Things to keep in mind
- security is multi-layered
- validation rules
- capability grants
- membrane proof
- encryption via call_remote
### Issues
- single point of failure (encrypting keys)