Files
quicproquo/docs/src/design-rationale/protocol-comparison.md
Chris Nennemann 853ca4fec0 chore: rename project quicnprotochat -> quicproquo (binaries: qpq)
Rename the entire workspace:
- Crate packages: quicnprotochat-{core,proto,server,client,gui,p2p,mobile} -> quicproquo-*
- Binary names: quicnprotochat -> qpq, quicnprotochat-server -> qpq-server,
  quicnprotochat-gui -> qpq-gui
- Default files: *-state.bin -> qpq-state.bin, *-server.toml -> qpq-server.toml,
  *.db -> qpq.db
- Environment variable prefix: QUICNPROTOCHAT_* -> QPQ_*
- App identifier: chat.quicnproto.gui -> chat.quicproquo.gui
- Proto package: quicnprotochat.bench -> quicproquo.bench
- All documentation, Docker, CI, and script references updated

HKDF domain-separation strings and P2P ALPN remain unchanged for
backward compatibility with existing encrypted state and wire protocol.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:11:51 +01:00

30 KiB

Comparison with Classical Chat Protocols

This page compares quicproquo against classical and legacy chat protocols -- IRC+SSL, XMPP (with and without OMEMO), Telegram's MTProto, and plain TCP/TLS chat systems -- to demonstrate what a modern, cryptographically rigorous design provides over protocols that were designed before end-to-end encryption, post-compromise security, and post-quantum readiness were practical concerns.

For a comparison against modern E2E-encrypted protocols (Signal, Matrix/Olm/Megolm), see Why This Design, Not Signal/Matrix/....


At a glance

            Classical IRC+SSL               quicproquo
            ─────────────────               ──────────────

 You ──TLS──▶ Server ──TLS──▶ Bob     You ──QUIC/TLS──▶ Server ──QUIC/TLS──▶ Bob
               │                                         │
          reads your                              sees only opaque
          plaintext                               MLS ciphertext
          messages                                (cannot decrypt)

The fundamental difference: classical protocols trust the server with your plaintext. quicproquo's server is cryptographically excluded from reading message content.


Protocol comparison matrix

Property IRC+SSL XMPP+TLS XMPP+OMEMO Telegram (MTProto) quicproquo
Transport encryption TLS (server-to-server optional) STARTTLS / direct TLS STARTTLS / direct TLS MTProto 2.0 (custom) QUIC + TLS 1.3
End-to-end encryption None None Double Ratchet (1:1) "Secret chats" only (1:1) MLS RFC 9420 (groups native)
Group E2E encryption None None Partial (OMEMO group) None (cloud chats) MLS ratchet tree
Forward secrecy TLS session only TLS session only Yes (Double Ratchet) Secret chats only Yes (MLS epoch ratchet + TLS)
Post-compromise security None None None (groups) None Yes (MLS Update proposals)
Server sees plaintext Yes Yes No (1:1); partial (groups) Yes (cloud chats) Never
Post-quantum readiness None None None None Hybrid KEM (X25519 + ML-KEM-768)
Group operation cost N/A (no E2E) N/A (no E2E) O(n) per member N/A (no group E2E) O(log n) via ratchet tree
Wire format Text (RFC 1459) XML XML + Protobuf TL (Type Language) Cap'n Proto (zero-copy)
Standardization RFC 1459 / RFC 2812 RFC 6120 / 6121 XEP-0384 Proprietary IETF RFC 9420 (MLS)
Authentication SASL / NickServ SASL / TLS client certs SASL + device fingerprints Phone number + SMS OPAQUE PAKE (password never leaves client)

Deep dive: IRC+SSL vs. quicproquo

IRC (Internet Relay Chat) is the archetypal chat protocol, designed in 1988. Adding SSL/TLS wraps the TCP connection in transport encryption, but the protocol's security model remains fundamentally unchanged.

What happens when Alice sends a message on IRC+SSL

┌───────┐         ┌──────────┐         ┌──────────┐         ┌─────┐
│ Alice │──TLS───▶│ Server A │──plain──▶│ Server B │──TLS───▶│ Bob │
└───────┘         └──────────┘         └──────────┘         └─────┘
                       │                    │
                  Sees: "PRIVMSG         Sees: "PRIVMSG
                   #secret :hey Bob,      #secret :hey Bob,
                   the password is         the password is
                   hunter2"                hunter2"

Problems:

  1. Server reads all plaintext. The IRC server receives, parses, and forwards every message in cleartext. TLS only protects the client-to-server hop.
  2. Server-to-server links may be unencrypted. IRC federation uses inter-server links that historically lack TLS. Even with modern IRCd configurations, each server in the network sees every message.
  3. No forward secrecy beyond TLS session. If a server's TLS private key is compromised, a passive attacker who recorded past traffic can decrypt all historical sessions (unless ECDHE was negotiated).
  4. No post-compromise security. There is no mechanism to recover from a key compromise. If a server is breached, all messages flowing through it are exposed indefinitely.
  5. No identity binding. NickServ password authentication is plaintext over the IRC protocol (inside TLS, but visible to the server). There is no cryptographic binding between a user's identity and their messages.

What happens when Alice sends a message on quicproquo

┌───────┐                    ┌────────┐                    ┌─────┐
│ Alice │──QUIC/TLS 1.3─────▶│ Server │──QUIC/TLS 1.3─────▶│ Bob │
└───────┘                    └────────┘                    └─────┘
    │                            │                            │
    │  MLS encrypt(              │  Sees only:                │  MLS decrypt(
    │    epoch_key,              │  0x8a3f...c7b2             │    epoch_key,
    │    "hey Bob,               │  (opaque blob,             │    ciphertext
    │     the password           │   cannot decrypt)          │  ) → "hey Bob,
    │     is hunter2"            │                            │       the password
    │  ) → 0x8a3f...c7b2        │                            │       is hunter2"
    │                            │                            │
    │  ◄── epoch advances ──►    │                            │
    │  old keys deleted          │                            │  old keys deleted
    │  (forward secrecy)         │                            │  (forward secrecy)

Key differences:

  • The server handles only opaque ciphertext. It cannot decrypt, modify, or selectively censor messages.
  • Each MLS epoch derives fresh keys. Past epoch keys are deleted -- even if the server is fully compromised, historical messages remain encrypted.
  • If Alice's device is compromised at epoch n, a single Update proposal heals the ratchet tree. Messages after epoch n+1 are protected (post-compromise security).

Deep dive: XMPP+OMEMO vs. quicproquo

XMPP with OMEMO (XEP-0384) adds end-to-end encryption via the Signal Double Ratchet protocol. This is a significant improvement over plain XMPP, but OMEMO inherits the limitations of the Signal Protocol for group messaging.

Group messaging comparison

              XMPP + OMEMO group (4 members)

   Alice encrypts separately for each member:
   ┌───────┐  ── encrypt(Bob_key) ──────▶  Bob
   │ Alice │  ── encrypt(Carol_key) ────▶  Carol
   └───────┘  ── encrypt(Dave_key) ─────▶  Dave
                  3 encryptions per message
                  O(n) cost per send

              quicproquo MLS group (4 members)

   Alice encrypts once with group epoch key:
   ┌───────┐  ── MLS_encrypt(epoch_key) ──▶  Server
   │ Alice │     1 encryption per message     │
   └───────┘     O(1) cost per send           ├──▶ Bob
                                              ├──▶ Carol
                                              └──▶ Dave
                                          (all decrypt with same epoch key)
Property XMPP+OMEMO groups quicproquo MLS groups
Encryption per message O(n) -- encrypt once per recipient O(1) -- single MLS application message
Add member O(n) -- distribute sender keys to all O(log n) -- single MLS Commit
Remove member O(n) -- rotate all sender keys O(log n) -- single MLS Commit
Post-compromise security No (sender keys have no PCS) Yes (any member can issue Update)
Group state consistency No formal guarantee MLS transcript hash ensures all members see identical state
Max practical group size ~100 (pairwise overhead) Thousands (log-scaling ratchet tree)

Deep dive: Telegram (MTProto) vs. quicproquo

Telegram is often perceived as a "secure" messenger, but its default mode provides no end-to-end encryption. Only "Secret Chats" (1:1 only, not available on desktop) use E2E encryption.

Telegram's two modes

  ┌──────────────────────────────────────────────────────────────────┐
  │                     Telegram Cloud Chats                        │
  │                   (default, all platforms)                      │
  │                                                                │
  │   You ──MTProto──▶ Telegram Server ──MTProto──▶ Recipient     │
  │                        │                                       │
  │                   Server decrypts,                             │
  │                   stores plaintext,                            │
  │                   indexes for search,                          │
  │                   processes for features                       │
  │                   (synced across devices)                      │
  └──────────────────────────────────────────────────────────────────┘

  ┌──────────────────────────────────────────────────────────────────┐
  │                    Telegram Secret Chats                        │
  │               (1:1 only, mobile only, opt-in)                  │
  │                                                                │
  │   You ──DH key exchange──▶ Recipient                          │
  │         (no PCS, no FS beyond initial DH,                      │
  │          no group support, proprietary crypto)                 │
  └──────────────────────────────────────────────────────────────────┘

Comparison

Property Telegram Cloud Chats Telegram Secret Chats quicproquo
Server reads plaintext Yes No No
Group E2E No N/A (1:1 only) Yes (MLS)
Forward secrecy None Limited (no ratchet) Full (MLS epoch ratchet)
Post-compromise security None None Yes
Cryptographic standard MTProto 2.0 (proprietary, custom) MTProto 2.0 IETF RFC 9420 (peer-reviewed)
Open source server No No Yes (MIT license)
Post-quantum None None Hybrid KEM (X25519 + ML-KEM-768)

Critical concern with Telegram: MTProto is a custom, proprietary cryptographic protocol that has not undergone the same level of independent cryptographic review as standard protocols (TLS, MLS, Signal Protocol). Multiple academic papers have identified weaknesses in earlier versions. quicproquo exclusively uses IETF-standardized protocols (TLS 1.3, MLS RFC 9420) and widely reviewed cryptographic primitives.


Practical attack scenarios

The following scenarios illustrate how the same attack plays out differently across protocol designs.

Scenario 1: Server compromise

An attacker gains root access to the chat server.

                          Attacker
                            │
                            ▼
┌──────────────────────────────────────────────────┐
│                   Chat Server                    │
├──────────────────────────────────────────────────┤
│                                                  │
│  IRC+SSL:     Full access to all messages.       │
│               Read history, impersonate users,   │
│               inject messages.                   │
│                                                  │
│  XMPP+TLS:   Full access to all messages.       │
│               Same as IRC.                       │
│                                                  │
│  Telegram:    Full access to cloud chat          │
│               plaintext. User photos, contacts,  │
│               message history all exposed.       │
│                                                  │
│  XMPP+OMEMO: Cannot read E2E messages, but      │
│               sees metadata (who talks to whom,  │
│               when, message sizes).              │
│                                                  │
│  quicproquo:                                 │
│               Cannot read messages (MLS E2E).    │
│               Sees metadata (recipient keys,     │
│               timing, sizes).                    │
│               Cannot inject valid messages       │
│               (lacks MLS group keys).            │
│               Cannot impersonate users           │
│               (lacks Ed25519 private keys).      │
│               Past messages remain encrypted     │
│               (forward secrecy).                 │
│               Future messages protected after    │
│               any member issues MLS Update       │
│               (post-compromise security).        │
│                                                  │
└──────────────────────────────────────────────────┘

Scenario 2: Harvest-now, decrypt-later (quantum threat)

A state-level adversary records all encrypted traffic today, planning to decrypt it with a future quantum computer.

  2025: Adversary passively records all ciphertext
  ─────────────────────────────────────────────────

  IRC+SSL (RSA/ECDHE):
    └── Quantum computer breaks ECDHE → all recorded sessions decrypted
        (and plaintext was already visible on the server anyway)

  XMPP+OMEMO (X25519):
    └── Quantum computer breaks X25519 → all recorded E2E messages decrypted

  Telegram (MTProto / custom DH):
    └── Quantum computer breaks DH → all recorded messages decrypted

  quicproquo (Hybrid KEM):
    └── Transport: QUIC/TLS with ECDHE → quantum computer breaks this layer
    └── Inner layer: MLS content encrypted with group epoch keys
        └── Hybrid KEM envelope: X25519 + ML-KEM-768
            └── Quantum computer breaks X25519 ✓
            └── Quantum computer breaks ML-KEM-768 ✗ (NIST Level 3, ~192-bit PQ)
            └── Combined key: STILL SECURE (both must be broken)

quicproquo's hybrid "belt and suspenders" design means that even if X25519 falls to a quantum computer, ML-KEM-768 protects the content. The adversary's recorded ciphertext remains useless.

Scenario 3: Device theft / compromise

An attacker steals Alice's unlocked device and extracts her key material.

  After device compromise at time T:
  ────────────────────────────────────

  IRC+SSL:
    Messages before T: visible on server (no E2E)
    Messages after T:  visible on server (no E2E)
    Recovery: change NickServ password (server-side only)

  XMPP+OMEMO:
    Messages before T: protected (forward secrecy via Double Ratchet)
    Messages after T:  exposed until sender key is rotated
    Group messages:    no PCS -- attacker reads all future group messages
                       until manual re-keying
    Recovery: manual device revocation + new sender keys

  Telegram (cloud):
    Messages before T: all accessible (stored on server in plaintext)
    Messages after T:  all accessible (cloud sync)
    Recovery: terminate session from another device

  quicproquo:
    Messages before T: protected (MLS forward secrecy, past epoch keys deleted)
    Messages after T:  exposed only until next MLS epoch advance
    Recovery: ANY group member issues an MLS Update proposal →
              new epoch key derived → attacker locked out
              (post-compromise security heals automatically)

Transport layer comparison

Why QUIC over TCP

Classical protocols (IRC, XMPP) use TCP, which suffers from head-of-line (HOL) blocking. quicproquo uses QUIC, which provides independent streams over UDP.

  TCP (IRC/XMPP): all streams share one ordered byte stream
  ─────────────────────────────────────────────────────────

  Stream A: ████████░░░░████████████    (blocked waiting for
  Stream B: ░░░░░░░░░░░░████████████     lost packet in A)
  Stream C: ░░░░░░░░░░░░████████████

  Lost packet ──▲
  in Stream A    │
                 └── ALL streams blocked until retransmit


  QUIC (quicproquo): each stream is independent
  ──────────────────────────────────────────────────

  Stream A: ████████░░██████████████    (only A waits)
  Stream B: ████████████████████████    (unaffected)
  Stream C: ████████████████████████    (unaffected)

  Lost packet ──▲
  in Stream A    │
                 └── Only Stream A waits; B and C continue

Connection establishment

  IRC+SSL: TCP handshake (1 RTT) + TLS handshake (1-2 RTT) = 2-3 RTT
  ──────────────────────────────────────────────────────────────────────
  Client ──SYN──▶ Server                          │
  Client ◀──SYN-ACK── Server                      │ TCP: 1 RTT
  Client ──ACK──▶ Server                          │
  Client ──ClientHello──▶ Server                  │
  Client ◀──ServerHello+Cert── Server             │ TLS: 1-2 RTT
  Client ──Finished──▶ Server                     │
  ════════════════════════════════════════════════════
  Total: 2-3 round trips before first message

  quicproquo: QUIC integrates crypto into handshake = 1 RTT (or 0-RTT)
  ──────────────────────────────────────────────────────────────────────────
  Client ──Initial(ClientHello)──▶ Server         │
  Client ◀──Initial(ServerHello)── Server         │ 1 RTT total
  Client ──Handshake(Finished)──▶ Server          │
  ════════════════════════════════════════════════════
  Total: 1 round trip (0-RTT with session resumption)

Authentication comparison

How users prove identity

  IRC:
    NICK alice
    PASS hunter2              ← password sent in plaintext (inside TLS)
    (NickServ sees password)  ← server stores/verifies password hash

  XMPP:
    SASL PLAIN: base64(alice:hunter2)  ← password sent to server
    (server verifies against stored hash)

  Telegram:
    Phone number + SMS OTP    ← carrier and Telegram see phone number
    (identity = phone number) ← no cryptographic identity

  quicproquo (OPAQUE PAKE):
    Client ──blinded_element──▶ Server    │ Server never sees password
    Client ◀──evaluated_element── Server  │ Mutual authentication
    Client ──finalization──▶ Server       │ Session key derived
    │                                     │
    └── password never leaves the client  │
        server stores only an opaque      │
        cryptographic record              │
        (Argon2id + Ristretto255)         │

OPAQUE (Oblivious Pseudo-Random Function + Authenticated Key Exchange) ensures that:

  1. The server never sees the plaintext password -- not during registration, not during login.
  2. The server stores only a cryptographic record that cannot be used for offline dictionary attacks without the client's cooperation.
  3. Argon2id key stretching makes brute-force attacks memory-hard.
  4. The login protocol produces a mutually authenticated session key, not just a server-verified credential.

Wire format efficiency

  IRC message (RFC 1459):
  ┌──────────────────────────────────────────────────────────┐
  │ :alice!alice@host PRIVMSG #channel :Hello everyone\r\n  │
  │                                                          │
  │ 56 bytes for 14 bytes of payload ("Hello everyone")      │
  │ Text parsing required. No schema. No type safety.        │
  │ Ambiguous parsing rules (RFC 1459 vs RFC 2812 conflicts) │
  └──────────────────────────────────────────────────────────┘

  XMPP message (XML):
  ┌──────────────────────────────────────────────────────────┐
  │ <message to='bob@example.com' type='chat'>              │
  │   <body>Hello everyone</body>                           │
  │ </message>                                              │
  │                                                          │
  │ ~120 bytes for 14 bytes of payload                       │
  │ XML parsing required (expensive). Verbose.               │
  │ Schema via XSD exists but rarely enforced at runtime.    │
  └──────────────────────────────────────────────────────────┘

  Cap'n Proto (quicproquo):
  ┌──────────────────────────────────────────────────────────┐
  │ [8-byte aligned struct with pointers]                    │
  │                                                          │
  │ ~40 bytes for 14 bytes of payload                        │
  │ Zero-copy: wire bytes = memory layout. No parsing step.  │
  │ Schema enforced at compile time via capnpc codegen.      │
  │ Canonical form: deterministic bytes for signing.         │
  │ Built-in async RPC (no separate HTTP/gRPC layer).        │
  └──────────────────────────────────────────────────────────┘

Security properties summary

The following diagram maps each protocol against the security properties it provides:

                        FS   PCS   E2E   E2E    PQ    Zero    Server   IETF
                       (1:1) (grp) (1:1) (grp)  ready  trust  excluded  std
                        │     │     │     │      │      │       │        │
  IRC+SSL               ·     ·     ·     ·      ·      ·       ·        ·
  XMPP+TLS              ·     ·     ·     ·      ·      ·       ·        ·
  XMPP+OMEMO            ●     ·     ●     △      ·      ●       ·        ·
  Telegram Cloud         ·     ·     ·     ·      ·      ·       ·        ·
  Telegram Secret        △     ·     ●     ·      ·      ●       ·        ·
  Signal                 ●     ·     ●     ●      △      ●       ·        ·
  quicproquo         ●     ●     ●     ●      ●      ●       ●        ●

  Legend:  ● = yes    △ = partial    · = no
  FS  = forward secrecy          PCS = post-compromise security
  E2E = end-to-end encryption    PQ  = post-quantum readiness
  Zero trust = server excluded from crypto
  Server excluded = server cannot read, modify, or forge messages
  IETF std = based on IETF-standardized protocol (RFC)

The quicproquo advantage: a layered defense

Classical protocols rely on a single layer of security (transport TLS). quicproquo applies defense in depth with three independent layers, each of which must be broken separately:

  IRC+SSL security layers:                quicproquo security layers:

  ┌─────────────────────────┐            ┌─────────────────────────────────┐
  │   TLS (transport)       │            │  Layer 3: Hybrid KEM envelope   │
  │   • server sees plain   │            │  • X25519 + ML-KEM-768          │
  │   • single point of     │            │  • post-quantum resistant       │
  │     failure              │            │  • both must be broken          │
  └─────────────────────────┘            ├─────────────────────────────────┤
                                         │  Layer 2: MLS (RFC 9420)        │
                                         │  • end-to-end group encryption  │
                                         │  • forward secrecy per epoch    │
                                         │  • post-compromise security     │
                                         │  • ratchet tree (O(log n))      │
                                         ├─────────────────────────────────┤
                                         │  Layer 1: QUIC + TLS 1.3       │
                                         │  • transport confidentiality    │
                                         │  • 0-RTT resumption             │
                                         │  • no head-of-line blocking     │
                                         │  • multiplexed streams          │
                                         └─────────────────────────────────┘

  To read a message, attacker must break:
  IRC+SSL:          TLS (1 layer)
  quicproquo:   TLS + MLS + Hybrid KEM (3 layers)

When would you still choose IRC?

Fairness demands acknowledging where classical protocols genuinely excel:

Advantage IRC quicproquo
Simplicity Telnet-compatible text protocol Binary protocol requiring client implementation
Maturity 35+ years of production use Early-stage research project
Federation Built-in multi-server mesh Single server per deployment
Client ecosystem Hundreds of clients on every platform CLI only (currently)
Low resource usage Runs on minimal hardware Requires modern TLS/QUIC stack
Public channels Designed for open, unencrypted discussion Designed for private, encrypted communication
Anonymity No identity required Requires Ed25519 identity keypair

IRC remains an excellent choice for public, open discussion where encryption is not needed and simplicity is valued. quicproquo is designed for a different threat model: private communication where confidentiality, forward secrecy, and post-compromise security are requirements, not luxuries.


Migration path: what changes for users

For users and operators coming from classical chat systems, here is what changes practically:

Concern Classical (IRC/XMPP) quicproquo
Server setup Install IRCd, configure TLS cert cargo build && ./qpq-server (auto-generates TLS cert)
Client setup Install any IRC client ./quicproquo-client register-user (generates Ed25519 identity)
Joining a group /join #channel Receive MLS Welcome message from group creator
Sending a message Type and press enter Same -- client handles MLS encryption transparently
Server admin sees messages Yes (always) No (never -- server sees only ciphertext)
Key management None (password only) Automatic -- MLS handles key rotation, epoch advancement
Device compromise recovery Change password Any group member issues Update -- automatic PCS recovery
Logging / compliance Server-side logging trivial Requires client-side export (server has no plaintext)

Further reading