From 0ca6b2b31a3858eb9c001881869e4dc55b92ec40 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Thu, 28 May 2026 17:58:23 -0400 Subject: [PATCH] how-it-works: explain what 'hi' becomes (AES-GCM scramble before volume) --- web/how-it-works.html | 44 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/web/how-it-works.html b/web/how-it-works.html index 6c4de39..81440a1 100644 --- a/web/how-it-works.html +++ b/web/how-it-works.html @@ -197,6 +197,46 @@
  • Pubkey — 1-to-1 ECDH (P-256) between two public keys.
  • +

    + The encryption happens before anything becomes volume, so the carrier + never holds the readable text — it holds scrambled bytes. Here is the + journey of "hi" in passphrase mode: +

    +
      +
    1. Plaintext. "hi" is two bytes of ASCII: + 0x68 0x69.
    2. +
    3. AES-256-GCM scrambles it. A fresh random 12-byte IV + (nonce) is generated and the two bytes are encrypted with the + passphrase-derived key, producing IV (12) + + ciphertext (2) + auth tag (16) = + 30 bytes. The ciphertext is the same length as the plaintext + (GCM is a stream mode) and looks like random noise: GCM XORs a key+IV + keystream into your bytes, turning 0x68 0x69 into two + unpredictable ones. Because the IV is random every time, sending + "hi" twice yields completely different ciphertext, so no + patterns leak.
    4. +
    5. Then it is framed, error-corrected, and modulated. A frame + header + CRC wrap the 30 bytes (~43 bytes); each byte becomes a 12-bit + Hamming codeword; each codeword becomes Gray-coded N-level volume steps on + the 440 Hz carrier.
    6. +
    +
    "hi" ─▶ AES-256-GCM ─▶ IV + ciphertext + tag (30 bytes, looks random) + ─▶ frame + CRC (~43 B) ─▶ Hamming(12,8) codewords ─▶ volume levels
    +

    + By the time it is volume, the readable h,i is gone + three layers up. Someone reading the volume locally (the same-UID PulseAudio + attack this project documents) demodulates the amplitude back to bytes and gets + 30 bytes of random-looking ciphertext, not "hi". Without the + passphrase the encryption is irreversible, and the auth tag means tampering + fails outright — flip one bit and decryption rejects it. +

    +

    + And it is doubled up: that is the application layer (AES-GCM). + WebRTC independently wraps the whole audio stream in DTLS-SRTP, + so the carrier is encrypted again in transit. Two separate keys, two separate + layers — the readable "hi" exists only in RAM on the two + endpoints, never on the wire and never in the volume. +

    Protects against a network observer reading chat content. Does not protect against another process on either endpoint recording the local audio, or an @@ -227,8 +267,8 @@