archy/.claude/plans/luminous-snacking-snowflake.md
Dorian 1ced0fdbf3 feat: Phase 3 Week 1 — X3DH key agreement + HKDF foundation
- 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>
2026-03-17 01:28:35 +00:00

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)

  1. core/archipelago/src/mesh/x3dh.rs
  2. core/archipelago/src/mesh/prekey.rs
  3. core/archipelago/src/mesh/ratchet.rs
  4. core/archipelago/src/mesh/session.rs
  5. core/archipelago/src/mesh/message_types.rs
  6. core/archipelago/src/mesh/outbox.rs
  7. core/archipelago/src/mesh/bitcoin_relay.rs
  8. core/archipelago/src/mesh/alerts.rs

Modified Files (8)

  1. core/archipelago/Cargo.toml — +hkdf, +lightning-invoice
  2. core/archipelago/src/mesh/crypto.rs — +hkdf_sha256, +ephemeral keygen
  3. core/archipelago/src/mesh/types.rs — +message_type, +typed payloads
  4. core/archipelago/src/mesh/listener.rs — typed dispatch, session bootstrap, relay
  5. core/archipelago/src/mesh/mod.rs — new submodules, new MeshService methods
  6. core/archipelago/src/api/rpc/mesh.rs — ~12 new RPC endpoints
  7. core/archipelago/src/api/rpc/mod.rs — register new routes
  8. neode-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