For a friend
Pollis is an app for sending messages, one-on-one, in a small group, or in larger spaces with channels. The thing that makes it different is that we, the people running Pollis, can't read what you write. Most messaging apps could if they wanted to. We can't.
The picture is a sealed envelope, but stronger than the paper kind. Before your message leaves your computer, it's locked inside a digital envelope that only the person you're writing to can open. We can't get inside. Even if our offices were broken into, the messages would stay unreadable. Groups work the same way: only the people currently in a group can open its messages. Someone who joins later can read what's said from the moment they joined onward, but not what came before. That's on purpose.
We've also been shrinking what's written on the outside of those envelopes. The stored record of a message no longer notes who sent it (only the people in the conversation can work that out, from inside the sealed contents) so if our database were ever stolen or handed over, it wouldn't show who said what. We also pad every text message out to a standard size before sealing it, so its length gives nothing away. One thing to be straight about: at the exact moment you hit send, our delivery server still has to check you're allowed to post in that conversation, so in that instant it does see it's you. Removing even that is something we're still working on.
If someone's cryptographic key ever changes silently (the kind of swap an attacker on our servers would attempt) Pollis catches it. A red shield badge appears next to their name in every conversation you share with them (direct messages, group member lists, channels), and an inline notice shows up in the chat so you can verify them again out-of-band. You only need to verify a person once: the green shield then follows them everywhere they appear in your account.
To use Pollis you sign in with your email (we send you a one-time code) and pick a four-digit PIN. The PIN unlocks the app on your computer, and after enough wrong guesses it erases your messages on that device. You also get a long backup code: save it somewhere safe. A password manager works. So does a piece of paper in a drawer. If you ever lose your computer or forget your PIN, that code is the only way back in. We don't keep a copy.
You can use Pollis on more than one device. Sign in on the new one, confirm a code on the old one, and the two agree privately to trust each other. New devices start empty (they don't get your old messages) but from then on, both devices receive everything going forward.
Files like pictures, documents, and voice notes are sealed the same way. Voice chat too: when you talk in a voice channel, the audio is sealed on your computer before it goes to our voice servers and only the other people in the channel can open it. The servers route packets they cannot listen to. The same group keys that protect your text messages produce the voice key, so anyone you've added to a channel can hear you and nobody else can.
A few honest trade-offs. Because we can't read your messages, we can't get them back for you if you lose everything. We can still see which conversations exist, who's in them, and roughly when they're busy, that's just how routing works. If somebody steals your computer while it's already unlocked, they can read your messages, because at that point it thinks they're you. And the privacy is only as strong as the people you're talking to.
One more thing you can check yourself: we now publish a fingerprint of every version of the app we release into a public list that can't be quietly edited. A small tool lets anyone confirm that the app they're running is one we've publicly published, so we can't secretly slip one person a tampered copy without it either showing up in that list forever or being obviously missing from it. (We're still working on letting outsiders rebuild the app from scratch and confirm it matches, byte for byte.)
That's the whole picture. It works like a normal messaging app, except we built it so we couldn't snoop even if we wanted to or were forced to. The cost is that you have to keep your PIN and backup code somewhere safe, there's no help desk that can let you back in.
How Pollis Keeps Your Conversations Private
Pollis is a desktop chat app for groups. If you have used Slack or Discord at work, or Microsoft Teams, you already know the shape of it: there are groups, there are channels inside groups, there are direct messages between people, there is voice, and there are files. The thing that makes Pollis different from those apps is what happens to the messages once they leave your device. In Slack, Teams, and Discord, the company that runs the service can read every message you send, because the server stores them in plaintext. In Pollis, the server cannot read them, because by the time a message reaches the server it has already been turned into ciphertext that can only be opened by the people you sent it to. This document explains how that actually works, in language that does not require a computer-science background, while still naming the specific cryptography involved so that anyone curious enough to look it up will be looking up the right things.
The starting point for any conversation about security is who you have to trust. With most messaging apps you trust three things implicitly: your own device, the company that built the app, and the company that runs the servers. With Pollis you trust your own device and you trust the version of the app you installed on the day you installed it. After that, you do not have to trust the servers at all. The remote database, the file storage, the voice routing service, the email service that delivers your sign-in code, all of those can be operated by people you have never met, and the design assumes those people are watching. The way this works is that everything sensitive happens on your device, before anything goes anywhere. Your messages are encrypted on the laptop in front of you. Your private keys are generated on the laptop in front of you and never leave it in a form anyone else can read. The server sees who is in which group, who is talking to whom, and how big the messages are, the same way a mail carrier sees the addresses on the envelopes they are carrying. It does not see what is inside the envelope. The difference between a real envelope and a Pollis envelope is that a real envelope can be steamed open by anyone determined enough to try; a Pollis envelope is sealed with mathematics, and the only person who has the matching key is the person it is addressed to.
Pollis also works to shrink what those envelope "addresses" reveal, and several of those improvements have now shipped. The server used to record, next to every stored message, which user sent it. It no longer does. Each message you send is now sealed so that the stored copy on the server carries only a meaningless placeholder where the sender used to be, and the person receiving it works out who really sent it from a cryptographic signature carried inside the sealed contents (something only the people in the conversation can read. The practical effect is that if the message database were ever stolen, subpoenaed, or quietly handed over, it would no longer show who sent what. The honest caveat is that this protects the stored records, not the live moment of sending: the delivery service that accepts your outgoing message still has to check that you are a member of the conversation, and that check still names you at the instant you send, until a further planned upgrade (called anonymous membership proofs) removes even that. Two smaller leaks are closed as well. The length of a text message is now padded out to one of a few fixed sizes before it is sealed, so the server can no longer tell a one-word reply from a long paragraph by measuring it (files are the exception) they are shared in a way that depends on their real size, so they are not padded). And the small real-time "you have a new message" ping that travels through the events server used to carry the sender's name; it now carries no sender at all, and is just a nudge to go and fetch the sealed message, whose true sender the recipient learns only after opening it.
The encryption Pollis uses for group chat is called MLS, which stands for Messaging Layer Security, and it is described in a public internet standard, RFC 9420. MLS was finalized in 2023 and was designed specifically for the problem of encrypting messages in groups that change over time, where people are added and removed, where people use multiple devices, and where the math has to keep working even when the group has thousands of members. It is the approach that Wire, Cisco Webex, and an increasing share of modern secure-messaging products are converging on. The library Pollis uses to implement it is called openmls, written in Rust. MLS does not hard-code which underlying algorithms are used; instead each group picks a numbered bundle of them, called a cipher suite. Pollis runs two, and the next few paragraphs explain both. The older of the two is the one the standard calls cipher suite one, and it combines four primitives. There is X25519, an algorithm for two devices to agree on a shared secret without ever transmitting that secret over the network. There is HKDF-SHA256, which takes a shared secret and shapes it into a key of the right size and form for the next step. There is AES-128-GCM, the actual cipher that scrambles the message, and which also includes a built-in tamper-check so that if anyone changes a single bit of the ciphertext in transit, the recipient will know and refuse to decrypt it. And there is Ed25519, a digital signature scheme that lets a device prove a message really came from the device that claims to have sent it. These four pieces, used together, are roughly the same security level as the encryption protecting your bank's website, with the difference that the keys here belong to your devices rather than to a central server.
The reason there is a second cipher suite is a problem usually called harvest now, decrypt later. X25519, the piece that lets two devices agree on a shared secret, is secure against every computer that exists today, but it is one of the algorithms that a sufficiently large quantum computer would break. No such machine exists, and it is an open question whether one ever will. What is not speculative is that an adversary with a lot of storage — a national intelligence service, say — can record encrypted traffic today and simply keep it, on the bet that the machine arrives before the contents stop mattering. A message you send this afternoon is protected by X25519 forever, including in a future where X25519 no longer protects anything. So Pollis's second cipher suite replaces the key agreement with something a quantum computer is not known to break: ML-KEM-768, the algorithm the American standards body NIST published in 2024 as FIPS 203 after an eight-year public competition. Pollis does not simply swap one for the other, because ML-KEM is comparatively new and a newly standardized algorithm occasionally turns out to have a flaw nobody spotted. Instead it runs both at once, combined by a construction called X-Wing, in a way where the resulting shared secret is safe as long as either algorithm holds. To read a Pollis message an attacker would have to break the well-tested classical algorithm and the new quantum-resistant one; breaking either alone gets them nothing. The second suite also swaps AES-128-GCM for ChaCha20-Poly1305, which is a cipher of equivalent strength; the reason is not any weakness in AES but a matter of which specific implementations Pollis is willing to run, and ChaCha20-Poly1305 is what the vetted quantum-resistant code path offers. Its signatures are post-quantum too, now that the follow-on work has landed: the second suite signs with ML-DSA-44, the scheme NIST published in 2024 as FIPS 204. Signatures are a genuinely different problem from encryption, and it is worth being precise about why. Harvest-now-decrypt-later does not apply to them: a forged signature only fools anyone at the moment a message is sent, so a quantum computer arriving in fifteen years cannot retroactively forge today's messages the way it could retroactively decrypt them. Where it does matter is anything that has to stay checkable for years — the identity keys that say which device is really yours, and above all the public transparency log, whose signed statements about history are supposed to be re-checkable indefinitely. Those are the reason Pollis moved. The cost is size, and it is not small: an ML-DSA-44 signature is 2,420 bytes against Ed25519's 64, and a public key 1,312 against 32.
Getting an existing group onto the new suite is the awkward part, because MLS deliberately does not let a group change cipher suite while it is running — the suite is baked into the group's identity at birth. Pollis therefore does not convert a group; it stands up a successor group on the new suite, moves the whole membership across in one step, and retires the old one. Each conversation keeps a generation counter so that everybody agrees which lineage is current and nobody is left talking into the retired one. The rule for when this happens is stricter than you might expect: Pollis waits until no device anywhere in the service is still on a version too old to speak the new suite. Waiting for just the current members would not be enough, because a group has to be sure that whoever gets invited tomorrow can also get in, and a group cannot know tomorrow's invitees by looking at itself. Devices that have not been seen in ninety days stop counting toward that requirement, which is what makes “everybody has updated” a condition that can actually be reached rather than one hostage to a laptop in a drawer. If Pollis cannot answer the question — if the check itself fails — it stays on the older suite rather than guessing, preferring a group that works to a group that is stuck. The honest edge is that this is forward-looking only: traffic that was already sealed under the classical suite before a group crossed over stays sealed under the classical suite. Nothing retroactively upgrades. What the migration buys is that everything from the crossing onward is out of reach of the harvest-now bet.
To understand what is actually being protected, it helps to understand the three layers of identity inside Pollis. The first layer is your account identity. Each user has one long-lived signing key, generated on the device where you first signed up. The mathematics here is ML-DSA-44, which produces a small private number that only your device knows, and a much larger corresponding public number that the server publishes for everyone else to see. When other people's devices want to verify that something really came from you, they check it against your public number. The private number, the one that actually proves who you are, never travels. The second layer is your device identity. Each laptop or computer you use Pollis on has its own unique identifier and its own signing key, separate from the account identity. The third layer is what MLS calls a leaf, which is the position your particular device occupies inside a particular group's encrypted state. Each device's leaf is signed by that device's signing key, and that signing key in turn is signed by your account identity key. This nesting is what protects you against a malicious server trying to insert a fake device into your account. If the server tried to slip in a phony device, that device would have no signature from your real account identity, and the other devices in the group would notice.
Beyond the protocol-level protection that cross-signing provides, Pollis also exposes a person-level check borrowed from Signal: safety numbers. Each pair of users in conversation has a sixty-digit number derived from both of their account identity public keys, displayed as twelve blocks of five digits. If you and the person you are talking to read the same number aloud, or scan each other's QR code, you have confirmed that the public key your device has for them is the same public key their device has for itself, meaning no one in the middle, including someone with full write access to the Pollis server, has swapped it. The number is reciprocal: both parties' devices independently produce the identical sixty digits using the same SHA-512 derivation, so either side can initiate the check. Until you do this manually for a given contact, their key is pinned the first time your device sees it, a model commonly called trust-on-first-use. The pinning happens silently on every direct message you exchange and on every group reconciliation that includes that person, so if the server later attempts to swap their public key for one it controls, your device notices the mismatch on the next exchange and surfaces a red shield in every conversation that person appears in, plus an inline notice in the chat. Verification is per-user, not per-conversation: once you have compared safety numbers with a colleague and marked them verified, that green shield follows them across direct messages, group member lists, and channel author labels for every group you share, automatically. If their key ever changes, the shield turns red in all those places at once, and you can re-verify them out-of-band before continuing to trust the conversation.
Signing in to Pollis works differently from a typical app, because of an old problem. In most apps, you type a password every time, and that password is what unlocks your account. Pollis does not have a password, because passwords get reused, get phished, and end up in breach lists. Instead, signing in for the first time on a device involves an email containing a six-digit code, sent through a service called Resend. You type the code back into the app, and that proves you control the email address. From that moment on, on that particular device, you stop using the email code and start using a four-digit PIN. The PIN is local to that one device. It is never sent anywhere, the company that built Pollis has no idea what your PIN is, and there is no way to recover it from the server because the server never knew it. What the PIN does is unlock a small encrypted file in your operating system's keychain. That file contains the actual cryptographic keys your device needs to decrypt your local message database and to sign things on your behalf. Without the PIN, even someone holding your laptop and looking inside the keychain only sees scrambled bytes.
The reason a four-digit PIN is enough to protect anything is a function called Argon2id. Argon2id is the current recommended algorithm for turning a low-entropy thing like a PIN into something hard to brute-force. The way it works is that it deliberately wastes a lot of memory and CPU time on a single attempt. Pollis tunes Argon2id to use sixty-four megabytes of memory and to take roughly a quarter of a second per try. That sounds fast, but consider that an attacker who has stolen a copy of your encrypted keystore would need to run that quarter-second computation for every guess, and there are ten thousand possible four-digit PINs. Combined with a hard cap of ten wrong tries before the encrypted material is deliberately deleted from your device, the math turns four digits, which sounds trivially weak, into something genuinely difficult to defeat. The encryption that wraps the keys themselves uses XChaCha20-Poly1305, a modern stream cipher with a built-in tamper check, chosen specifically because its very long random number used per encryption makes certain rare implementation mistakes impossible.
The PIN protects the device. The Secret Key protects your account. When you first sign up for Pollis, the app shows you a string that looks like A3-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX, six groups of five characters separated by dashes. Those characters come from a thirty-two character alphabet, the digits zero through nine plus the letters of the alphabet, with the letters I, L, O, and U deliberately removed because they are easy to confuse with one and zero. There are thirty random characters in the body, which works out to a hundred and fifty bits of entropy. To put that in perspective, a randomly chosen twenty-character password using upper case, lower case, digits and symbols is roughly a hundred and thirty bits of entropy, and that is already considered far beyond brute-forceable. A hundred and fifty bits is not just impractical to guess but, given the energy that would be required, physically unreasonable to guess. The Secret Key is what allows you to recover your account on a brand new device when you have no other devices logged in. The server stores a copy of your account identity key, but it stores it locked inside an encrypted box, and the only key that opens that box is the Secret Key, which the server does not have. The cryptography here uses HKDF-SHA256 to turn the Secret Key into an unlocking key, and AES-256-GCM to do the actual unwrapping. Pollis shows the Secret Key to you exactly once, and you are expected to write it down somewhere safe, treat it like the deed to a house. If you lose it, and you also lose every device you were ever signed in on, your account is gone. There is no support line that can recover it because there is no support line that has the key to recover it with.
When you want to sign in to Pollis on a second device, two paths exist. The friendlier path is approval by another device. The new device makes up a temporary pair of cryptographic keys, displays a random six-digit verification code, and asks the server to forward a notice to your other devices. One of those other devices shows you the same six-digit code, and asks if it matches. When you confirm, that device performs a calculation called Diffie-Hellman key agreement, using X25519, with the temporary key the new device sent. The result of that calculation is a shared secret that only the two devices know, even though the math happened in plain sight on the server. They use that shared secret, run through HKDF-SHA256 and then AES-256-GCM, to wrap your account identity key, and the new device unwraps it. The six digits you compared are the human-checkable part of the protocol. Even an attacker who could read and write the server's database cannot inject a false approval, because they would not know what code your real device showed you, and the user would notice the mismatch. The fallback path is the Secret Key recovery flow, which is the same idea but uses your Secret Key instead of an existing device. Either way, once a new device has the account identity key, it sets a fresh PIN, publishes its own device certificate signed by the account identity key, and joins every group you are a member of via a feature of MLS called external commit, where it inserts itself into the group's encrypted state using a public snapshot the group leaves behind for exactly this purpose.
The data that lives on your laptop is also encrypted. The local database file, which is where decrypted messages, group state, and various caches are stored, is opened through a system called SQLCipher, which is a fork of the SQLite database that adds page-level encryption. The encryption underneath is AES-256 in CBC mode, with HMAC-SHA512 over each page protecting against tampering. The key that opens the database is a thirty-two byte random number, generated on first sign-up, and stored only in the keystore, only as ciphertext under the PIN-derived key. If somebody copies your hard drive while the app is locked, what they get is a file that is mathematically indistinguishable from random noise. The local database deliberately does not contain things like your contact list or the list of groups you belong to, because those are fetched from the server and do not need to live on disk. This separation means that a stolen laptop, with the PIN unknown to the thief, leaks nothing useful, while the trade-off is that an offline laptop cannot remind you of the names of people you talk to until it gets back online for a moment.
Files and images go through a separate path called convergent encryption. When you upload a photo, the app first computes a fingerprint of the file, called a SHA-256 hash. It then runs that fingerprint through HKDF-SHA256 to derive both the encryption key and the random number used for that one upload. The key encrypts the file using AES-256-GCM, in chunks of four megabytes at a time so that very large files do not have to be loaded into memory all at once. The encrypted blob, plus the fingerprint, is what gets uploaded to Cloudflare R2. The interesting consequence is that two different people uploading the same image end up at the same R2 object, and the system can avoid storing two copies. The interesting cost is that an attacker who already has a candidate image, in plaintext, can compute the same fingerprint and ask the server whether anyone has uploaded that exact image. They cannot read it, but they can confirm or deny its presence. This is the same trade-off used by services like MEGA. Pollis accepts it as the price of cross-user deduplication; if a future audit decides the trade-off is wrong, it can be replaced with per-conversation keys at the cost of dedup.
Voice is end-to-end encrypted on the same footing as text. When you join a voice channel, the underlying transport between your device and our LiveKit server is the same DTLS-SRTP that every WebRTC application uses, including Slack Huddles, Microsoft Teams, and Google Meet. By itself, that transport encryption stops at the server: LiveKit is a selective forwarding unit, an SFU, which means it receives audio from each participant and forwards it to the others. In a normal WebRTC deployment the SFU sees plaintext audio in the moment, which is the gap that lets services like Slack Huddles or Google Meet be wiretapped by the operator. Pollis closes that gap by turning on a second layer of encryption, applied to each audio frame after it has been compressed by the Opus codec but before it leaves the device. The library that does this is libwebrtc's FrameCryptor, exposed through the LiveKit Rust crate, and it uses AES-128-GCM on every frame. The SFU still routes the RTP packets, because the packet headers stay readable, but the payload it is forwarding is ciphertext it cannot open. The same design is what Discord ships in their 2024 protocol called DAVE, and what the LiveKit JavaScript SDK exposes as setupE2EE.
The voice key is derived from your channel's MLS group, the same group that protects the text messages in that channel. Specifically, Pollis takes the MLS exporter secret at the current epoch, mixes in the label pollis/voice/v1 and the epoch number as context, and uses the resulting thirty-two bytes as the shared symmetric key for the voice channel. Because every member of the MLS group already holds the exporter secret, every member derives the same voice key without the server ever seeing or touching it. When the group's membership changes (somebody is added, somebody is removed) MLS advances the epoch, and Pollis immediately re-derives the voice key from the new exporter secret and rotates it on the live call without anyone reconnecting. New members start hearing audio from the moment the new epoch lands; removed members lose the ability to decrypt the next frame. The defaults match the LiveKit JavaScript SDK so a future mobile or web client could interoperate. There is no opt-out and no configuration: voice is always encrypted this way.
There are several other limitations worth being explicit about. The bearer tokens that the desktop app uses to talk to Turso, Cloudflare R2, LiveKit, and Resend are baked into the app binary itself, which is common for desktop apps that ship without a per-user authentication service in front of their backend providers. Anyone willing to take apart the app can extract those credentials and open a database connection equivalent to any client. They still cannot decrypt anything because of MLS, but they can read metadata at the level the server already sees. The verification of cross-signing certificates on inbound MLS commits currently logs a loud warning rather than refusing the commit, because refusing would freeze the local copy of the group at an old state while the rest of the world moved on; closing this gap requires a more complex catch-up protocol that is on the roadmap. Rotation of a device's own MLS keys — the thing that heals a group after a device has been compromised — is driven by the app running, not by a background timer. Your device rotates its key material in every group as soon as it joins, and after that whenever it starts up and finds its key material in a group is more than about a week old, with a small random spread so that a large group's devices do not all rotate on the same day. That is a real change from the earlier design, where nothing rotated unless the membership happened to change, but it is not a clock: healing happens the next time the app is opened, so a group whose members are all offline for a month does not heal during that month. There is no backup of message history of any kind: a brand-new device installed three months from now will not be able to read messages from before it joined, because the cryptography MLS uses, called TreeKEM, is built around forward secrecy that makes that genuinely impossible without a backup mechanism, and the product principle Pollis is built on says no backup mechanism. If you forget your PIN and have lost your Secret Key, your account is unrecoverable. These are not bugs. They are deliberate trade-offs that prefer privacy over convenience in the small number of cases where the two collide.
One thing on that list of things you have to trust has recently gotten easier to check: the app itself. Everything above assumes the copy of Pollis running on your computer is the honest one (the same program whose source code anyone can read. An ordinary code signature only proves that Pollis's own signing key produced the file; it does not prove the file matches the public source, and it would not stop a version secretly built to backdoor a single person. Pollis now publishes a fingerprint of every release it ships into a public, append-only log at verify.pollis.com) the same kind of tamper-evident log already used for account keys and group history. Anyone can run a small command-line tool, pollis-verify release, to confirm that the version they are holding is one Pollis has publicly and permanently recorded, trusting nothing but a single fixed key rather than Pollis's word. That makes it very hard for anyone (including a Pollis operator under legal compulsion) to quietly hand one user a tampered build: its fingerprint is either in the public log for all time, or conspicuously missing from it. Being honest about the edges, this proves what Pollis published for a given release, and it is not yet the whole story. The builds are not yet reproducible byte-for-byte from source by an independent party, there is no second, Pollis-independent signature anchor yet, and there is no in-app "verify this build" button yet; those pieces are still being built. Until reproducibility lands, the log proves the bytes Pollis published, not yet that those bytes match the public source, which is the part an outside rebuilder will eventually confirm.
Compared to apps you have probably used, the picture is roughly this. Signal and WhatsApp encrypt your messages end to end the same way Pollis does, but they use the older Signal Protocol with X3DH and the Double Ratchet, designed in 2014; Pollis uses the newer MLS, which is better suited to large groups and to people with multiple devices. Slack and Microsoft Teams do not encrypt your messages end to end at all; the server reads everything. Enterprise add-ons such as Slack Enterprise Key Management and Microsoft 365 Customer Key let large customers control the encryption keys used at rest, but those features are about key custody, not end-to-end encryption (the server still has access to plaintext for indexing, search, and compliance. Discord is in the Slack camp for messages) the server reads chat, but its 2024 DAVE protocol does provide end-to-end encryption for voice and video; Pollis applies the same kind of frame-level encryption to its voice channels, keyed off the MLS group, so the two are comparable on the voice axis. Element and Matrix encrypt their group chat, but with a different system called Megolm, which trades some of the post-compromise security MLS provides for the ability to back up message history through the server, which Pollis intentionally does not do. iMessage encrypts messages but pairwise rather than at the group level, and by default backs up to iCloud in a form Apple holds the keys to; users who turn on Apple's Advanced Data Protection get an end-to-end encrypted backup, but it's an opt-in. The closest analog to Pollis in cryptographic shape is Wire, which also uses MLS through OpenMLS, in roughly the same configuration. The closest analog to Pollis in product shape is Slack, with the difference that the server cannot read your messages.
The summary, in plain words, is this. Pollis encrypts your messages on your computer, with keys that exist only on your computers, before sending them anywhere, using a modern public standard called MLS that is broadly considered the right way to do this in 2026. Your local data is encrypted on disk under a key that itself is encrypted under your PIN. Your account is recoverable to a new device only by an existing device of yours, or by a one-hundred-and-fifty-bit Secret Key that only you have, and is unrecoverable otherwise. Files are encrypted before they leave your computer. Voice is also encrypted before it leaves your computer, using a key derived from the same MLS group that protects your messages, so the voice server forwards ciphertext it cannot decode. The full technical writeup, with citations to the specific RFCs and parameter choices, lives alongside this document for anyone who wants to verify the claims rather than take them on faith.