- Add hkdf = "0.12" dependency for Double Ratchet key derivation
- Extend mesh/crypto.rs with hkdf_sha256, hkdf_sha256_32, hkdf_sha256_64,
and generate_x25519_ephemeral() for DH ratchet steps
- Create mesh/x3dh.rs: full X3DH key agreement protocol
- PrekeyBundle generation with Ed25519-signed prekeys
- 3-way (or 4-way) ECDH → HKDF-SHA256 → root key
- Initiator and responder sides derive identical root key
- CBOR encoding for mesh transmission
- Bundle signature verification
- 5 unit tests: generate+verify, both-sides-same-key,
without-one-time-prekey, cbor-roundtrip, tamper-detection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6.2 KiB
Phase 3 & 4: Encrypted Mesh Messaging + Off-Grid Bitcoin Operations
Context
Phase 1 built the mesh radio layer (Meshcore protocol, serial driver, basic chat). Phase 2 added transport abstraction (Mesh>LAN>Tor routing, CBOR delta sync, Reed-Solomon chunking). Current encryption is static X25519 shared secret per peer — no forward secrecy, no message type discrimination, no store-and-forward.
Phase 3 adds Signal-style Double Ratchet for forward secrecy, typed messages (ALERT, INVOICE, COORDINATE, PSBT_HASH), and store-and-forward relay. Phase 4 adds off-grid Bitcoin operations: block header relay, transaction relay, Lightning invoice relay, and emergency alert system with dead man's switch.
Dependencies to Add
hkdf = "0.12" # KDF for Double Ratchet chains
lightning-invoice = "0.34" # BOLT11 parsing (LDK standard, MIT)
Custom Double Ratchet from existing crypto (ed25519-dalek, curve25519-dalek, chacha20poly1305, sha2, hmac) — no DR crate needed.
Architecture
mesh/
├── x3dh.rs — X3DH key agreement (prekey bundles, 3-way ECDH)
├── ratchet.rs — Double Ratchet state machine (forward secrecy)
├── session.rs — Per-peer session manager (ratchet state persistence)
├── prekey.rs — Prekey store (signed + one-time prekeys, rotation)
├── message_types.rs — Typed message envelope (TEXT/ALERT/INVOICE/COORDINATE/PSBT_HASH)
├── outbox.rs — Store-and-forward queue (24h TTL, relay hops)
├── bitcoin_relay.rs — TX relay, Lightning relay, block header announce
├── alerts.rs — Emergency alerts, dead man's switch
└── (existing files extended: crypto.rs, listener.rs, types.rs, mod.rs)
Implementation Steps
Week 1: X3DH + HKDF Foundation
New: mesh/x3dh.rs, mesh/prekey.rs
Modify: Cargo.toml (+hkdf), mesh/crypto.rs, mesh/mod.rs
PrekeyBundle: identity_key + signed_prekey + one_time_prekeys (CBOR, ~200B)PrekeyStore: disk persistence at{data_dir}/prekeys/, rotation, consumption- X3DH: 3-way ECDH → HKDF-SHA256 → root key for Double Ratchet
- ARCHY:3 identity broadcast with embedded prekey bundle
Week 2: Double Ratchet Protocol
New: mesh/ratchet.rs (~500 LOC), mesh/session.rs (~300 LOC)
RatchetState: DH ratchet keypair, root key, send/recv chain keys, counters, skipped keys (max 100). HKDF-SHA256 chains + ChaCha20-Poly1305 per-message.
Wire format: 40B header (DH pub + counters) + 12 nonce + ciphertext + 16 tag = 68B overhead. Single frame: 64B plaintext. Chunked: ~2.4KB.
SessionManager: HashMap<DID, RatchetState>, lazy load from {data_dir}/ratchet/{did_hash}.json. Backward compat: falls back to static shared secret for ARCHY:2 peers.
Week 3: Typed Messages + Store-and-Forward
New: mesh/message_types.rs, mesh/outbox.rs
Modify: mesh/types.rs, mesh/listener.rs
CBOR envelope: [0x02] [{ t: u8, v: bytes, ts: u32, sig?: bytes }]
Types: TEXT(0), ALERT(1), INVOICE(2), PSBT_HASH(3), COORDINATE(4), PREKEY_BUNDLE(5), SESSION_INIT(6)
GPS as Coordinate { lat_microdeg: i32, lng_microdeg: i32 } — integer only, no float.
MeshOutbox: VecDeque, 24h TTL, max 3 relay hops, disk persistence. Checked every 10s tick.
Week 4: RPC Endpoints + Session Bootstrap
Modify: api/rpc/mesh.rs, api/rpc/mod.rs, mesh/listener.rs
New RPC: mesh.send-invoice, mesh.send-coordinate, mesh.send-alert, mesh.outbox, mesh.session-status, mesh.rotate-prekeys
Prekey distribution via ARCHY:3 broadcasts. Session init via X3DH on first message to new peer.
Week 5: Off-Grid Bitcoin (Phase 4)
New: mesh/bitcoin_relay.rs, mesh/block_headers.rs
Modify: Cargo.toml (+lightning-invoice), api/rpc/mesh.rs
Block header relay: Internet node broadcasts BlockHeaderAnnouncement (height, hash, Ed25519 sig) on new block. Mesh-only peers display "SPV sync via mesh".
TX relay: Mesh-only node sends raw tx hex → internet peer calls sendrawtransaction → returns txid.
Lightning relay: Create invoice → send bolt11 → peer pays → proof-of-payment returned.
Week 6: Emergency Alerts + Dead Man's Switch
New: mesh/alerts.rs
DeadManSwitch: Background task, configurable interval (default 6h), broadcasts signed ALERT with GPS to emergency contacts when triggered. Auto-check-in on any authenticated RPC.
RPC: mesh.alert-configure, mesh.alert-checkin, mesh.alert-test, mesh.alert-status
Week 7: Frontend
Modify: stores/mesh.ts, views/Mesh.vue, mock-backend.js
Message rendering by type: invoice (orange card + Pay button), alert (red card), coordinate (blue card + OSM link), psbt_hash (gray card + Review).
Session indicator: shield icon (green=ratchet, yellow=static, gray=none).
Block height in off-grid banner. Alert config panel. Dead man switch toggle.
Week 8: Integration Test + Deploy
E2E on .228 (internet) + .198 (mesh-only): X3DH handshake, 50-message ratchet, invoice relay, TX relay, block headers, dead man switch. Deploy to both servers.
New Files (8)
core/archipelago/src/mesh/x3dh.rscore/archipelago/src/mesh/prekey.rscore/archipelago/src/mesh/ratchet.rscore/archipelago/src/mesh/session.rscore/archipelago/src/mesh/message_types.rscore/archipelago/src/mesh/outbox.rscore/archipelago/src/mesh/bitcoin_relay.rscore/archipelago/src/mesh/alerts.rs
Modified Files (8)
core/archipelago/Cargo.toml— +hkdf, +lightning-invoicecore/archipelago/src/mesh/crypto.rs— +hkdf_sha256, +ephemeral keygencore/archipelago/src/mesh/types.rs— +message_type, +typed payloadscore/archipelago/src/mesh/listener.rs— typed dispatch, session bootstrap, relaycore/archipelago/src/mesh/mod.rs— new submodules, new MeshService methodscore/archipelago/src/api/rpc/mesh.rs— ~12 new RPC endpointscore/archipelago/src/api/rpc/mod.rs— register new routesneode-ui/src/views/Mesh.vue— typed rendering, alert UI, session badges
Verification
cargo test --all-features -- mesh::ratchet mesh::x3dh mesh::session
cargo clippy --all-targets --all-features
cd neode-ui && npm run type-check
./scripts/deploy-to-target.sh --both