Skip to content

Latest commit

 

History

History
207 lines (106 loc) · 9.67 KB

File metadata and controls

207 lines (106 loc) · 9.67 KB

0. Reference implementation (sonicdrop-rs)

The canonical codebase is the Rust crate under sonicdrop-rs/ (Tokio, libp2p, SQLite, Protobuf). Where this document uses formulas or abstract names, the exact wire layouts, HKDF info strings, and defaults are defined in source - notably:

  • Crypto & addressing: sonicdrop-rs/src/crypto/mod.rs (compute_target_hash, derive_session_key, inner payload AES-GCM with AAD = H_target).
  • Onion: sonicdrop-rs/src/network/onion.rs (layer encryption, ephemeral Ed25519, HKDF labels layer_store / layer_relay).
  • Protocol state machine: sonicdrop-rs/src/protocol/{send,receive,resend,epoch}.rs.
  • Persistence: sonicdrop-rs/migrations/*.sql, sonicdrop-rs/src/state/.
  • Network runtime: sonicdrop-rs/src/network/{dht,unified,onion_transport}.rs.
  • Handshake (ultrasonic + WAJ): sonicdrop-rs/src/handshake/.

See ARCHITECTURE.md for a full module map and sonicdrop-rs/SPEC_GAP_CHECKLIST.md for spec-vs-code parity. SECURITY.md lists the Rust stack’s HKDF salt/info inventory.


1. Protocol Architecture & Philosophy

SonicDrop is an asynchronous, high-latency messaging protocol designed for "Metadata-Free" communication. Unlike standard instant messengers (which rely on a central server routing messages between sockets), Sonic-Drop treats the network as a passive storage medium.

  • Topology: A Distributed Hash Table (DHT) overlay network where nodes act as temporary storage silos (Inboxes).

  • Directionality: Communication occurs on two mathematically distinct, unidirectional tracks ($A \to B$ and $B \to A$).

  • Addressing: Addresses are ephemeral. They exist only for the duration of a message's Time-To-Live (TTL) and are derived deterministically.


2. Phase 1: The Ultrasonic Handshake (Session Zero)

Objective: To establish a shared cryptographic state and a "Root of Trust" without relying on internet infrastructure or Public Key Infrastructure (PKI).

Mechanism:

Alice and Bob meet physically. Their devices perform an air-gapped Diffie-Hellman exchange using near-ultrasonic frequencies (18kHz-24kHz). This band is chosen to prevent remote interception (audio attenuates quickly) while remaining audible to standard hardware microphones/speakers.

The Shared State ($S_0$):

At the end of the handshake, both devices possess:

  1. Root Key ($K_{root}$): The master secret derived via ECDH.

  2. Epoch Nonce ($E$): Initialized to $0$.

  3. State Counters: $C_{A\to B} = 0$, $C_{B\to A} = 0$.

  4. The Backup Pool ($P_{backup}$): A list of $n$ high-uptime, static nodes (Entry Nodes) used solely for "Epoch Recovery" (Phase 5).


3. Phase 2: The Sender Protocol (Deterministic Drop)

Context: Alice ($A$) intends to send Message $M$ to Bob ($B$).

3.1. Deterministic Addressing

Alice does not send the message to Bob. She calculates where Bob will be looking. She derives the Target_Hash for the current counter index.

$$H_{target} = \text{SHA256}(K_{root} \parallel E \parallel \text{"A->B"} \parallel C_{A\to B})$$

Alice performs a DHT lookup to find the neighborhood of nodes responsible for $H_{target}$. She selects the top $q$ closest nodes (redundancy set $I_{1...q}$) to ensure availability if one node goes offline.

3.2. Payload Construction

To ensure message ordering and replay protection, the internal payload is structured as follows:

$$Payload = \text{AES-GCM}_{K_{session}}(\text{Protobuf(InnerPayload)})$$

The payload is encoded as protobuf InnerPayload (header, message_body, counter, timestamp, resend metadata), then encrypted under AES-GCM with H_target as AAD.

  • Local History: Alice caches this payload in her local Buffer_History (a hash map keyed by $C_{A\to B}$) for $r$ generations to facilitate potential future resends.

3.3. Onion Routing (The "Store" Command)

Alice constructs a nested onion packet. Unlike Tor (which focuses on a stream), this is a packet-switched "Drop" command. She selects $n$ relays ($R_1...R_n$).

The final layer (the exit node/Inbox) receives a specific instruction:

CMD: STORE

KEY: $H_{target}$

VAL: $Payload$

Once the packet is injected into the network, Alice immediately increments $C_{A\to B}$.


4. Phase 3: The Inbox Protocol (Oblivious Storage)

Context: A storage node ($N$) receives a decrypted packet.

The node is "oblivious" - it does not know who sent the packet (Alice is hidden by the Onion layers) nor who will retrieve it (Bob has not requested it yet).

  1. Validation (on onion path): Relay/inbox nodes that unwrap onion layers verify the per-layer Ed25519 signature before accepting the layer content.

  2. Storage: $N$ stores VAL at KEY in its local Kademlia-style table.

  3. TTL: A strict timer (e.g., 24 hours) is initiated. Upon expiration, the data is scrubbed. This provides Forward Secrecy; if Bob's key is compromised next week, messages sent today are already deleted from the network.


5. Phase 4: The Receiver Protocol (Windowed Harvest)

Context: Bob comes online. He calculates the addresses for his "Lookahead Window" - the next $w$ expected messages.

$$List_{inboxes} = { \text{Addr}(E, \text{"A}\to\text{B"}, C_{read} + k) \mid k \in [0, w] }$$

5.1. The Parallel Sweep

Bob queries these addresses.

  • Cover Traffic: To an outside observer, Bob is querying random DHT hashes. If $w=5$, but only 1 message exists, the other 4 lookups act as natural dummy traffic.

  • Retrieval: Bob downloads any data found.

5.2. Gap Detection & Management

Bob attempts to decrypt all blobs.

  • Success: He updates his local $C_{read}$ to the highest contiguous index.

  • Failure (The Gap): If Bob retrieves Message #5 and #7, but #6 returns 404 Not Found, he adds #6 to his Missing_Set.

5.3. The Reply (Piggybacked NACK)

Every outgoing message includes a Header section. When Bob's Missing_Set is non-empty, he embeds a "Negative Acknowledgment" (NACK) vector in the header of his next outgoing message on the $B \to A$ chain.

$$Payload_{B \to A} = \text{AES-GCM}_{K_{session}}(\text{Header: NACK_Vector}[6] \parallel M_{reply} \parallel C_{B\to A} \parallel \text{Timestamp})$$


6. Phase 5: Resiliency (Forward-Moving Recovery)

Context: Alice receives Bob's message and sees NACK_Vector:[6].

Alice does not try to re-upload to Address #6. That address is "dead" (compromised, offline, or timed out).

The Encapsulated Resend:

  1. Alice retrieves $M_6$ from her local buffer.

  2. She wraps $M_6$ inside a special frame called a Resend_Tombstone.

  3. She transmits this inside her current outgoing message slot (e.g., #51).

$$Payload_{#51} = \text{AES-GCM}_{K_{session}}(\text{FLAG: RESEND} \parallel \text{Orig_ID: } 6 \parallel M_6 \parallel \text{Current_ID: } 51)$$

Bob receives #51, unpacks it, identifies the resend flag, and virtually "backfills" slot #6 in his local database, allowing the conversation stream to resolve.


7. Phase 6: The "Ring of Safety" (Epoch Reset)

Context: A catastrophic desynchronization (counters drift too far, or the conversation has been dormant for months).

  1. Beaconing: Bob polls the pre-shared Backup Pool nodes ($B_{1...k}$). These act as "Dead Drop of Last Resort."

  2. Hard Resync: Bob posts a HARD_RESYNC blob encrypted to Alice using X25519 ECDH, HKDF-SHA256 (SonicDrop_backup_v1 / hard_resync), and AES-256-GCM, containing a new random Epoch Nonce ($E_{new}$). Only Alice, who holds the corresponding private key, can decrypt the command.

  3. Discovery: Alice, realizing the main chain is dead, polls the Backup Pool, finds the Resync command, decrypts it with her persistent X25519 private key, and updates her global state.

  4. Replenishment: Upon the first successful message exchange on the new Epoch (tracked via an epoch_backup_exchanged flag), Alice and Bob exchange a list of new Backup Nodes to replace the ones they just utilized, preventing analysis of the static backup addresses. The flag resets on each epoch transition.


8. Enhancements

8.1. Storage Availability Delay

Incoming messages are held for a random delay (default 1-5 seconds) before becoming retrievable. This breaks the tight time correlation between send and receive events, making traffic analysis attacks harder.

8.2. Dummy / Chaff Traffic

Nodes generate fake STORE commands to random peers at configurable intervals. This ensures real traffic is indistinguishable from background noise.

8.3. Disk Persistence

Inbox storage persists to SQLite on disk, allowing nodes to survive restarts without losing queued messages.

8.4. Session Key Derivation via HKDF

Per-direction AES-256 session keys are derived from $K_{root}$ using HKDF-SHA256 with direction and epoch info strings:

$$K_{session} = \text{HKDF}(K_{root}, \text{salt}=\text{"SonicDrop_session_v1"}, \text{info}=\text{"session_

_epoch_"})$$

8.5. Ed25519 Onion Layer Signatures

Each onion layer includes an Ed25519 signature over the encrypted inner payload. Relay nodes verify the signature before performing ECDH decryption, providing sender authentication independent of the AES-GCM tag.


9. Default Parameters

Parameter Symbol Default Description
Buffer retention $r$ 50 Messages cached for potential resend
Lookahead window $w$ 5 Addresses queried per sweep cycle
Message TTL - 86 400 s (24 h) Inbox expiry time
Relay hops $n$ 2 Onion routing relay count
Redundancy $q$ 3 Storage nodes per message