1# Protocol
2
3Full specification: [`docs/protocol.md`](https://github.com/richardmetzner/SophaxChat/blob/main/docs/protocol.md)
4
5---
6
7## Wire format
8
9All messages are JSON-encoded, signed with the sender's Ed25519 identity key, and wrapped in a `WireMessage` envelope before being handed to the transport layer (BLE/WiFi mesh or TCP/Tor).
10
11```
12WireMessage {
13 type: WireMessageType // see enum below
14 senderID: String // SHA-256(IK_pub) — derived, never a username
15 recipientID: String? // nil for broadcasts
16 payload: Data // encrypted content (type-dependent)
17 signature: Data // Ed25519(senderIdentityKey, payload)
18 timestamp: UInt64 // sender wall clock (ms) — used for display only
19 messageID: String // UUID for dedup
20 ttl: UInt8 // relay hop counter, max 6
21}
22```
23
24---
25
26## 1:1 Session lifecycle
27
28```
29Alice Bob
30 │ │
31 │── Hello (PreKeyBundle) ────────────────▶ │ IK_A, SPK_A, OTPK_A, avatar
32 │ │ Bob runs X3DH receiver:
33 │ │ SK = KDF(DH₁ ‖ DH₂ ‖ DH₃ ‖ DH₄)
34 │ │ Init Double Ratchet with SK
35 │◀─ Hello (PreKeyBundle) ──────────────── │ (symmetric)
36 │ │
37 │── InitiateSession ────────────────────▶ │ Alice's ephemeral key + encrypted first msg
38 │ (X3DH sender, DR init) │ Bob decrypts, session established
39 │ │
40 │══ Message (Double Ratchet) ════════════ │ Per-message keys, forward secrecy
41 │◀═ Message (Double Ratchet) ════════════ │
42```
43
44### X3DH key material
45
46| Key | Type | Purpose |
47|---|---|---|
48| IK (Identity Key) | X25519 | Long-term identity — never changes |
49| SPK (Signed Prekey) | X25519 | Medium-term — rotated every 7 days |
50| OTPK (One-Time Prekey) | X25519 | Single-use — consumed on session init |
51| EK (Ephemeral Key) | X25519 | Per-session — generated by sender |
52
53Shared secret: `SK = HKDF(DH(IK_A, IK_B) ‖ DH(EK_A, IK_B) ‖ DH(EK_A, SPK_B) ‖ DH(EK_A, OTPK_B))`
54
55---
56
57## Group session lifecycle
58
59SophaxChat supports two group encryption modes:
60
61### Sender Keys v2 (default)
62
63Each member maintains an independent HMAC-SHA256 ratchet chain. No shared group key exists.
64
65```
66Alice joins group G
67 ├─ Generates SenderKeyState: chainKey, messageCount, createdAt
68 ├─ Distributes SenderKeyDistribution to all members
69 │
70Per message:
71 ├─ messageKey = HMAC-SHA256(chainKey, 0x01)
72 ├─ chainKey = HMAC-SHA256(chainKey, 0x02) ← ratchet forward
73 └─ ChaChaPoly(messageKey, plaintext) → ciphertext
74```
75
76Auto-rotation triggers: **500 messages** or **7 days**, whichever comes first.
77
78### MLS — RFC 9420 (opt-in)
79
80MLS groups use `mls-rs` (Rust, compiled to XCFramework via UniFFI) with the RustCrypto backend. Each epoch provides post-compromise security. Migration from SKv2 → MLS is available via `GroupCryptoMigration`.
81
82---
83
84## Relay routing
85
86Messages not directly deliverable are wrapped in a `RelayEnvelope` and broadcast:
87
88```
89RelayEnvelope {
90 innerMessage: Data // sealed — relay cannot read content or identity
91 ttl: UInt8 // starts at 6, decremented each hop
92 messageID: String // LRU dedup cache (capacity 500) prevents loops
93}
94```
95
96A node relays if `ttl > 0` and `messageID` is not in its dedup cache. Maximum path: 6 hops (~300m Bluetooth radius per hop).
97
98---
99
100## Message types
101
102| Type | Description |
103|---|---|
104| `hello` | PreKeyBundle broadcast on peer connect |
105| `initiateSession` | X3DH + first DR message |
106| `message` | Normal Double Ratchet message |
107| `ack` | Delivery acknowledgement |
108| `readReceipt` | Read receipt (blue tick) |
109| `typingIndicator` | Ephemeral typing state |
110| `groupInvite` | Group membership invitation |
111| `groupMessage` | Encrypted group message |
112| `senderKeyDistribution` | SKv2 chain distribution / rotation |
113| `senderKeyRequest` | Request fresh SKD after stale key detected |
114| `reaction` | Emoji reaction on a message |
115| `editMessage` | Edit a previously sent message |
116| `deleteMessage` | Delete a message |
117| `relay` | Multihop relay envelope |
118| `deadDrop` | Unauthenticated broadcast (offline delivery) |