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.
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.