How End-to-End Encryption Works: A Developer's Guide
When a service claims “end-to-end encryption,” they’re making a specific technical promise: that data is encrypted on your device before transmission and can only be decrypted on the recipient’s device. The servers in between handle only ciphertext—encrypted data that looks like random noise without the decryption key.
This matters because it changes the trust model fundamentally. With ordinary transport encryption, you trust that the service provider won’t read your data. With end-to-end encryption, the service provider cannot read your data, even if compelled by law enforcement or compromised by attackers. The mathematical properties of the encryption make it impossible.
Understanding how this works requires grasping three concepts: asymmetric encryption for establishing secure channels, key exchange for agreeing on shared secrets, and the practical protocols that combine these primitives into usable systems.
The Foundation: Asymmetric Encryption
Traditional encryption uses a single key for both encryption and decryption. If Alice wants to send Bob a secret message, they must first agree on a key, then Alice encrypts with that key, and Bob decrypts with the same key. The obvious problem: how do Alice and Bob agree on a key without an attacker intercepting it?
Asymmetric encryption solves this through mathematical one-way functions. Each participant generates a pair of keys: a public key they share openly and a private key they guard carefully. The keys are mathematically related but distinct. Data encrypted with someone’s public key can only be decrypted with their corresponding private key.
RSA, invented in 1977, was the first widely-adopted asymmetric algorithm. Its security rests on the difficulty of factoring large numbers into their prime components. Generating an RSA key involves selecting two large prime numbers, multiplying them together to produce a modulus, and deriving the public and private exponents through modular arithmetic. The public key is the modulus and public exponent; the private key is the modulus and private exponent. Anyone can encrypt using the public key, but only the holder of the private key can decrypt.
Modern systems increasingly use elliptic curve cryptography (ECC) instead of RSA. ECC achieves equivalent security with much smaller keys: a 256-bit elliptic curve key provides roughly the same security as a 3072-bit RSA key. This matters for performance and bandwidth. Cloudflare’s benchmarks showed that ECC operations can be 20 to 116 times faster than equivalent RSA operations for TLS handshakes. Mobile devices and IoT sensors particularly benefit from the reduced computational requirements.
The most popular elliptic curve for modern cryptography is Curve25519, designed by Daniel Bernstein with resistance to implementation errors as a primary goal. Unlike the NIST curves that preceded it, Curve25519’s design choices are fully documented and justified, leaving no room for speculation about hidden weaknesses.
Establishing Shared Secrets: Key Exchange
Asymmetric encryption is computationally expensive. Encrypting large amounts of data—like a terminal session—directly with RSA or ECC would be impractically slow. Instead, asymmetric encryption is used to establish a shared secret, which then becomes the key for fast symmetric encryption algorithms like AES.
The Diffie-Hellman key exchange, published in 1976, demonstrated that two parties could agree on a shared secret over an insecure channel without ever transmitting that secret. The mathematics involves modular exponentiation. Alice and Bob agree on public parameters: a large prime number and a generator. Alice picks a secret number, computes the generator raised to that power modulo the prime, and sends the result to Bob. Bob does the same with his own secret and sends his result to Alice. Each can now compute the shared secret by raising the received value to their own secret power. An eavesdropper who sees both transmitted values cannot compute the shared secret without solving the discrete logarithm problem, which is believed to be computationally infeasible for properly chosen parameters.
X25519 is the modern incarnation of Diffie-Hellman, using Curve25519 instead of modular arithmetic. It provides 128 bits of security with 256-bit keys and is designed for constant-time implementation, which prevents side-channel attacks that extract secrets by measuring how long operations take.
A critical refinement is ephemeral key exchange. Rather than using the same keys repeatedly, participants generate fresh key pairs for each session. This provides forward secrecy: if an attacker later compromises a long-term key, they still cannot decrypt past sessions because those sessions used different ephemeral keys that no longer exist.
The Signal Protocol: State of the Art
The Signal Protocol, originally developed for the Signal messaging app and now used by WhatsApp, Facebook Messenger, and others, represents the most thoroughly analysed end-to-end encryption system in widespread use.
Signal faces a challenge that simpler encryption schemes don’t: asynchronous communication. When Alice messages Bob, Bob might be offline. The message must be stored on a server until Bob comes online, but it must be encrypted such that the server cannot read it. Meanwhile, neither Alice nor Bob can perform an interactive key exchange because they’re not online simultaneously.
The X3DH (Extended Triple Diffie-Hellman) protocol solves this. Bob pre-publishes several types of keys to the server: his long-term identity key, a signed prekey that rotates monthly, and a bundle of one-time prekeys that are each used once and discarded. When Alice wants to initiate a conversation, she fetches Bob’s key bundle from the server and performs multiple Diffie-Hellman operations combining her ephemeral key with Bob’s various published keys. The result is a shared secret that Alice can use immediately for encryption, which Bob can reconstruct later when he comes online.
Once a conversation is established, the Double Ratchet algorithm maintains forward secrecy for every message. Two “ratchets” operate simultaneously. A symmetric ratchet advances with each message, deriving new encryption keys from previous ones through a key derivation function. A Diffie-Hellman ratchet advances whenever a message round-trip occurs, incorporating fresh key material. The combination means that compromising any single message key reveals nothing about past or future messages.
These properties—forward secrecy, post-compromise security, and asynchronous operation—make the Signal Protocol suitable for applications where communication patterns are unpredictable and security requirements are high.
What E2EE Protects (and What It Doesn’t)
End-to-end encryption protects message content. An attacker who intercepts encrypted messages, or an insider at the service provider, sees only ciphertext. Without the decryption keys, which exist only on the endpoints, the content is inaccessible.
Metadata is a different matter. E2EE typically does not hide who is communicating with whom, when communications occur, how frequently, or the sizes of messages. This metadata can reveal significant information. Former NSA Director Michael Hayden famously noted that intelligence agencies “kill people based on metadata.” Knowing that someone contacts a particular journalist, or calls a crisis hotline, or communicates intensively with someone before a significant event can be as revealing as the content itself.
Some systems attempt to protect metadata through additional mechanisms. Signal’s Sealed Sender feature encrypts the sender’s identity so that Signal’s servers don’t know who sent a message. Onion routing, as used by Tor, obscures communication patterns by routing traffic through multiple relays. But these protections are separate from E2EE itself and involve their own trade-offs in complexity and performance.
Another limitation: E2EE protects data in transit and at rest on servers, but it cannot protect data on compromised endpoints. If an attacker installs malware on your device, they can read messages after decryption or capture keystrokes before encryption. E2EE assumes the endpoints themselves are secure, which is why device security remains essential even with encrypted communications.
E2EE vs. Transport Encryption
The distinction between end-to-end encryption and transport encryption causes frequent confusion because both involve encryption.
Transport Layer Security (TLS), the protocol that secures HTTPS connections, encrypts data between your device and a server. When you connect to Gmail over HTTPS, your email is encrypted during transmission. But Gmail’s servers decrypt your email to process it—indexing it for search, scanning it for spam, storing it in your mailbox. Google can read your email because TLS only protects the connection, not the data at rest on their servers.
With end-to-end encryption, the service never sees plaintext. A properly implemented E2EE email service receives your encrypted message and stores it encrypted. The decryption key exists only on recipient devices. The service literally cannot read the email, even if they wanted to, even under legal compulsion.
This distinction has practical implications. When evaluating a service’s privacy claims, ask: where does decryption occur? If the answer is “on the server,” you’re trusting the service provider. If the answer is “only on recipient devices,” you’re trusting mathematics.
E2EE in Practice: Terminal Sharing
Terminal sharing tools illustrate how E2EE principles apply beyond messaging.
sshx, a modern terminal sharing tool, uses end-to-end encryption based on a clever URL fragment mechanism. When you start a session, sshx generates a URL like sshx.io/s/gzN0WHsm6r#tiOAVOLsNXEZxJ. The portion after the hash—the fragment identifier—is never sent to the server. Web browsers don’t include fragments in HTTP requests; they’re processed entirely client-side.
sshx uses this fragment to derive an encryption key through Argon2, a memory-hard key derivation function designed to resist brute-force attacks. All terminal input and output is encrypted with AES using this derived key before transmission to sshx’s servers. The servers relay encrypted data between participants but cannot decrypt it because they never receive the URL fragment that generates the key.
This design means you can share a terminal session with genuine confidence that the relay infrastructure cannot observe your commands or their output. The trade-off is that losing the full URL (including fragment) means losing access—there’s no recovery mechanism because no one else has the key.
klaas takes a similar approach with open-source clients. Because the client code is publicly available, developers can verify that encryption occurs before data leaves their machine. You don’t have to trust claims about encryption; you can read the implementation and, if you’re sufficiently motivated, build the client yourself from audited source code.
Verifying E2EE Claims
How do you know a service actually implements end-to-end encryption rather than merely claiming to?
Open-source clients provide the strongest verification path. If you can read the code that runs on your device, you can trace exactly what happens to your data before it’s transmitted. You can verify that encryption occurs locally with keys that never leave your device. You can check that the encryption algorithm is implemented correctly. Several tools exist to assist: static analysis can identify cryptographic operations, and network traffic inspection can confirm that transmitted data appears random (as ciphertext should).
Closed-source clients require more trust, but independent audits help. Reputable services commission security audits from firms like NCC Group, Trail of Bits, or Cure53. These audits typically include source code review, cryptographic analysis, and penetration testing. Published audit reports provide evidence that claims match implementation, though you’re ultimately trusting the auditors.
Protocol documentation matters too. The Signal Protocol is thoroughly documented, with formal security proofs published in academic literature. When a service says they “use the Signal Protocol,” that claim is verifiable against public specifications. Vague claims like “military-grade encryption” or “bank-level security” should prompt skepticism; these terms are marketing rather than technical descriptions.
For terminal sharing specifically, you can inspect network traffic with tools like Wireshark or mitmproxy. If a tool claims E2EE but you can read session content in captured packets, the claim is false. If packets contain only random-looking data of consistent sizes, that’s consistent with (though not proof of) proper encryption.
The Trade-offs
End-to-end encryption isn’t free. It introduces complexity that simpler approaches avoid.
Key management becomes the user’s problem. If you lose your private key, your data is gone—there’s no “forgot password” recovery option because no one else has the key. Services work around this with key backup mechanisms, but those mechanisms can undermine E2EE if implemented poorly. iCloud backups of Signal messages, for example, may not be E2EE unless you specifically enable that option.
Multi-device usage requires careful handling. Your encryption keys must somehow exist on all your devices, which means either generating separate keys per device (and managing the complexity that implies) or securely transferring keys between devices (and accepting the risks that implies).
Server-side features become impossible or limited. A service cannot search your encrypted emails on the server because it can’t read them. It cannot scan for malware. It cannot provide “smart” features that require analysing content. Either these features are omitted, or they require client-side processing that may be slower or more battery-intensive than server-side equivalents.
Compliance and legal interception become contentious. Law enforcement agencies argue that E2EE protects criminals. Service providers argue that weakening encryption for “good guys” inevitably weakens it for everyone. This debate is ongoing and has led to legislative proposals in various jurisdictions that would effectively prohibit strong E2EE.
Despite these trade-offs, end-to-end encryption has become the expected standard for sensitive communications. Messaging apps that don’t offer it face justified criticism. As AI assistants gain access to our terminals and codebases, the same expectation is extending to developer tools. Understanding how E2EE works—not just that it exists—helps you evaluate whether a tool’s implementation actually delivers the security it promises.
Questions? Join our GitHub Discussions or reach out on 𝕏 @klaas_sh.
Related Articles

