Skip to main content

Protocol Reference

How End-to-End Encryption Works

Simple IRC Client can encrypt your direct messages so that only you and the person you're talking to can read them. This page opens up SIC-E2EE and shows, step by step, what actually happens between your keyboard and the wire.

PROTOCOLSIC-E2EE v1 CIPHERAES-256-GCM KEY EXCHANGEECDH P-256 ยท 3DH STATUSOPEN SOURCE

FIG. 1 — KEY EXCHANGE, NO SERVER INVOLVED

01 — THE HANDSHAKE

Two clients agree on a secret, in public

When you start an encrypted conversation, your client and your peer's client run a short handshake before a single encrypted message is sent. Your client generates a fresh, one-time key pair and sends it alongside your long-term identity key in a PRIVMSG-based OFFER. Their client answers the same way with ACCEPT.

Neither message hands over the session key itself. Both sides separately compute it using a Triple Diffie-Hellman calculation (3DH) over the identity and ephemeral keys, then run the result through HKDF-SHA256 with a transcript hash as salt. The IRC server, and everyone relaying your connection, only ever sees two opaque CTCP lines — it has no way to derive what you both just agreed on.

Because the session key depends on ephemeral keys generated fresh for that conversation, a copy of your long-term identity key alone can't decrypt messages from a past session — a property known as forward secrecy.

02 — THE CIPHER

Every message, the same six steps

Once both sides hold the same session key, every message follows the same pipeline before it reaches the wire:

AES-256-GCM is an authenticated cipher: it produces ciphertext and a tag proving nothing was tampered with in transit, and every frame gets a fresh nonce. Long messages are chunked and reassembled on the other end with a 30-second window for out-of-order delivery. A client that doesn't speak SIC-E2EE just sees an unrecognized CTCP request and ignores it — that's what lets encrypted and unencrypted users share the same network without breaking. Even /me actions go through this pipeline; there's no plaintext fallback for an encrypted conversation.

03 — KEYS THAT NEVER LEAVE

Private keys your own code can't read

FIG. 4 — NON-EXTRACTABLE KEY STORAGE

Every IRC network gets its own identity key pair, generated once and kept in IndexedDB as a non-extractable WebCrypto CryptoKey. That's a deliberate constraint of the Web Crypto API: once a key is marked non-extractable, no JavaScript on the page — including a malicious script from an XSS bug — can read the private key material as raw bytes. Signing and key derivation happen inside the browser's own crypto engine; your key exists, but nothing in the client's code can print it, upload it, or ever needs to.

A separate identity per network also means a service you talk to on one IRC network can't correlate you with the same nickname on another — your fingerprint on one network says nothing about who you are elsewhere.

04 — ALWAYS-VISIBLE TRUST

Encryption you can check, not just trust

Encryption without a way to check who you're actually talking to isn't worth much on its own — in principle, anyone able to intercept your handshake could offer their own key instead of your peer's. A lock icon in the conversation header keeps the state of every conversation visible at a glance:

  • Verified: encrypted, fingerprint confirmed.
  • Unverified: encrypted, identity not yet compared.
  • Mismatch: peer's key changed unexpectedly.
  • Off: plaintext, readable by the server.

Encrypting a conversation doesn't wait on verification — the moment you or your peer starts one, messages are protected end-to-end, and the "unverified" state above is just the normal starting point, not a warning to clear. Verifying is there for when you want to rule out interception at the very first handshake: your client spells out each side's fingerprint using the NATO phonetic alphabet, one word per hex digit (e.g. Zero One Two Three…) — the same internationally standard scheme used to read letters and numbers unambiguously over a phone or radio — over a channel you both already trust: a phone call, an existing verified conversation, in person. If a peer's key ever changes after you've verified them, or a previously-encrypted conversation quietly drops back to plaintext, you get a warning before your next message goes out instead of a silent, unnoticed downgrade.

05 — SCOPE

What this protects, and what it doesn't

Being precise about the edges of a security feature matters as much as the feature itself. Here's the honest boundary of SIC-E2EE:

COVERED

  • Content of direct messages and actions between two Simple IRC Client users
  • Forward secrecy per session, via ephemeral keys
  • Tamper detection, via the AES-GCM authentication tag
  • Reading by the IRC server and network operators
  • Passive eavesdropping on the network path

OUT OF SCOPE

  • Group channels — messages there are visible to everyone in the room by design
  • Metadata — that you're talking to someone, when, and how often
  • A compromised device — encryption can't protect a key someone can already read off your machine
  • A peer's client that doesn't implement SIC-E2EE — the conversation just won't offer to encrypt
  • Denial of service — handshake flooding is rate-limited to 1 OFFER/peer/second, not eliminated

Read the code, don't just take our word for it

SIC-E2EE is fully open source. The protocol and its implementation are on GitHub for anyone to audit.