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