---
# System prepended metadata

title: P2P Messaging with Encryption

---

# 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)
