CHANNELIn testingNotify me

Encryption in CHANNEL Messenger

Last updated: October 16, 2026. This page describes what cryptography this app uses, what it uses it for, and what it does not do. It exists because we answer questions about encryption to Apple, to Google, and under US export regulations, and those answers should be checkable against something rather than taken on faith.

Publishing this costs us nothing in security. A cryptographic system should remain secure when everything about it except the private keys is public — that principle is older than the field itself, and a design that depends on secrecy of its own description was already broken. If anything here looks wrong to you, we would rather hear about it.


1. The algorithms

We use standard, published algorithms and we do not invent cryptography. Every primitive below is a public specification with a long history of analysis.

AlgorithmSpecificationWhat we use it for
X25519RFC 7748Key agreement between two devices
ML-KEM-768FIPS 203Post-quantum key agreement, always together with X25519, when two phones begin a conversation through Find me by or pair in person (below)
Ed25519RFC 8032Signatures on pairing messages and on published key bundles, proving they came from a given identity
ChaCha20-Poly1305RFC 8439Encrypting message contents, with authentication
HKDF-SHA256RFC 5869Deriving separate keys from one shared secret, so no key is used for two purposes
SHA-256FIPS 180-4Hashing, and deriving the delivery addresses described below
MLSRFC 9420Encrypting posts in a formal group, with the algorithms above (X25519, Ed25519, ChaCha20-Poly1305, SHA-256), through the OpenMLS library
AES-256-GCMNIST SP 800-38DEncrypting what CHANNEL stores on your phone, view-once files, and a backup file you export
PBKDF2-HMAC-SHA256RFC 8018Turning a passphrase into the key for that backup file (300,000 rounds), and a PIN into a verifier (210,000)

For messages, ChaCha20-Poly1305 rather than AES is a deliberate choice. It is designed to run in constant time in software without special hardware, which matters on the range of phones this app has to work on. A backup file is the one place AES is used instead, because it is encrypted by the phone's own library rather than by our protocol, and both platforms have a hardware-accelerated implementation of it.

PBKDF2 rather than Argon2id, and that is a compromise rather than a preference. Argon2id is the better answer to somebody guessing a passphrase offline, and there is no Argon2 on either platform without adding a dependency. The rounds above are the honest version of that trade, and it is written down here rather than left in the source so that anybody who disagrees can say so.

2. What is standard and what is ours

Two different things get called “the encryption”, and the distinction is worth being clear about.

The mathematics is entirely standard. We wrote none of it and we would not. Home-made cryptography is the most reliable way to build something that looks secure and is not.

The arrangement is ours. How a message is framed, which bytes are authenticated alongside the ciphertext and in what order, how a delivery address is derived from keys and the current time, and how a device decides whether to send over Bluetooth, Wi-Fi, a local network or the internet — all of that we designed. No standards body has reviewed it, because it is specific to this app.

Ours is not the same as secret. It is written down in full, and we are glad to share the detail with anyone who wants to examine it — see the contact address at the end.

3. What the encryption is for

Message contents

Message text is encrypted on the sending device and decrypted on the receiving device. Our server holds no secret key of yours and cannot read anything passing through it. It does hold public keys, and §4 says which ones and what that costs. When two phones are close enough to reach each other directly over Bluetooth or Wi-Fi, no server is involved at all.

Formal groups

A formal group's posts are sealed once, on the phone that sends them, under a key every current member holds and nobody else does. The key changes whenever somebody joins or leaves, so a member who has left cannot read what comes after. This is MLS, the IETF's published standard for group encryption. In a formal group each member takes part under a key made for that group alone, not the key that identifies them to their contacts, so the members of one group cannot link each other to another group or to a contact card. Our server holds the sealed posts for up to 30 days and cannot read them.

Addressing

Messages waiting on the server are not filed under a name, a phone number or an account. They sit under a token derived from cryptographic keys and the current time period, which changes regularly. The server cannot tell you who owns one, and two tokens belonging to the same person in different time periods do not look related.

A value you publish under Find me by — a phone number, an email address, an @handle — is addressed differently, and it is the one address here that does not rotate. It is a plain SHA-256 of the value itself, so every phone derives the same one, and so does anyone else holding the value. That is what lets somebody reach you at a number with no directory to ask. It is also the limit of the claim: somebody who already has your number can ask our server whether that number is published on CHANNEL, and get an answer. Publishing a value is how you say you want to be reachable at it, so that answer is the feature rather than a leak. The reverse is narrower than it sounds. The server holds no values, and it files each record under a second hash of the slot, keyed with a secret it holds apart from the records, so a copy of the records alone matches no list of numbers. The set of phone numbers is small enough to try in full, so whoever holds both the records and that key can hash every number and match, recovering each published number and the public keys at it. The server also sees the slot in each request while it answers it. An email address or a handle cannot be listed that way, only tested once guessed. A value nobody has published or invited answers exactly as a value belonging to nobody does.

Who sent it

The sender's identity is inside the encrypted portion, not attached to the outside. The server learns that something arrived for some address. It does not learn who sent it.


4. Pairing: what it does, and what it proves

Pairing performs a real key agreement, on both platforms. When two people pair, their phones run a three-message exchange: each contributes a fresh ephemeral X25519 key, every message is signed under the sender's Ed25519 identity key over a fixed-length transcript, and the shared secret is the output of that exchange. It appears in none of the messages that travel. Anyone who kept every byte of them, our own server included, learns nothing from them.

The first message of the exchange is unauthenticated, deliberately, and no pairing route asks the two of you to compare a code.

Six digits under a button labelled Numbers Match would get a tap, not a comparison, and a check almost nobody performs claims more than it delivers. So nothing stops to ask for one, and CHANNEL never prints Verified on the strength of one. A contact’s page does show a Safety Number, eight groups of five digits worked out from your key and theirs and the same on both phones, for anyone who wants to compare it in person or on a call. It is optional: nothing asks for it, there is no badge and no “unverified” state, and a conversation works the same whether or not you ever open it. If the two numbers match, nobody is between you. If they do not, the way you were connected is the thing to check.

What protects a pairing by code, with or without that comparison, is where the code came from. The pairing code is not a secret and never was: it carries a public key, so reading it buys an eavesdropper nothing. Forging it is the threat, and a code you read off a screen in front of you cannot be forged, because there is nowhere for anyone to stand. Each attempt also carries a fresh random value, so the rendezvous address it names is used by that one attempt and no other.

So the app records how each contact was linked and shows it on their card — Linked by code when a code passed between you, Linked by contact when you wrote to something they had published. Those are facts about what happened rather than a ceremony.

The honest residual risk is a code that reaches you through a channel somebody else can rewrite — a text, an email, a forwarded message. That is what splitting a code across two channels is for: forging it then means rewriting every part consistently, and one honest channel makes the checksum fail.

None of this proves who is holding a phone, and that is what your own judgement is for. The practical way to settle it is a video call with somebody you already know: a face and a voice answer the question a key cannot, and CHANNEL places one, sealed between the two phones like everything else. A CHANNEL call is announced by a push, so it can reach a phone that is locked; a call from an Android phone to an iPhone does not always reach it.

Reaching somebody who has not paired with you

When you publish a value under Find me by, your phone leaves a small signed bundle of public keys at that value's address, and our server hands it to anyone who asks for it. That is what lets a stranger seal a first message to you while your phone is switched off, rather than both of you having to be awake at the same moment. Nothing secret is in the bundle, and it is signed by your identity key.

The cost is that the server is the one handing that key out. A server that chose to misbehave could hand out a bundle of its own and read the first exchange, and there is nothing on the screen that would tell you — the signature binds the prekey to an identity key, so replacing one means replacing both, and you have no earlier copy of a stranger's identity to compare it against. Accepting pairs you with the identity in that invitation, and everything afterwards is an ordinary end-to-end conversation with whoever that is. Pairing with a code you read off the other person’s screen does not have this limit, because the code carries the key itself. For a person you reached through a published value, the Safety Number on their contact page is the check: a substituted key shows as a different number. Comparing is optional, and a video call with somebody you already know is the other way to be sure who it is.

Post-quantum protection when a conversation begins

The threat is “record now, decrypt later”. Somebody who copies encrypted traffic today and keeps it can try to open it years from now, with a quantum computer large enough to break X25519. Every key in a CHANNEL conversation descends from the secret the two phones agree when it begins, so protecting that one agreement protects everything that comes after it.

What CHANNEL does. Your phone publishes two key bundles under Find me by: the X25519 one, and beside it one that also carries an ML-KEM-768 key (FIPS 203, the standard NIST published for post-quantum key agreement). When you write to somebody through a value they published, or pair in person with a code, and both phones carry this, the starting secret comes from X25519 and ML-KEM together. An attacker has to break both to recover it: a quantum computer that breaks X25519 still faces ML-KEM, and a flaw found in ML-KEM still leaves X25519 standing.

What stays classical, stated plainly. Contacts paired before both phones carried this keep the secret they agreed then. Formal groups use MLS with its own classical suite. Signatures are Ed25519, so someone who held a quantum computer at the moment two phones paired could still pose as one of them; the protection here is against a recording opened later. And each step of the ratchet below adds a fresh X25519 secret, so a phone stolen after pairing, together with a quantum computer, would read the messages that follow the theft.

Signal and Apple's iMessage use the same family of hybrid key agreement. The full description, with every byte, is in the protocol, section 4.9.

Forward secrecy, and what it does not cover.

The key that seals a message changes as you go. CHANNEL runs its own implementation of Signal's published Double Ratchet, in the core both apps share: every message moves the key on, and each reply mixes in fresh key material from the other phone. So if somebody takes the current key off a phone, it does not open the messages that were sent before — even if they kept copies of them as they traveled.

Limits, stated rather than left to be discovered. It applies between two phones whose builds both carry it; a message to a phone on an older build is sealed with the key set at pairing. It protects messages in transit, not the conversations saved on a phone, which the app lock and the phone’s own encryption protect. A phone replaces the prekey that opens invitations and first messages every 7 days, keeps its eight most recent, so an invitation, handle, code or QR code made against a recent one still opens; whoever takes a prekey secret from a phone can read the invitation and first messages sent to that prekey, and the fresh keys the ratchet mixes in protect what follows. And it is our construction of a published design, tested with the test suites and fuzzing described on the Security page and reviewed by outside AI models, which that page names, with every finding checked against the code and the real ones fixed. No independent human audit has been done.

Signing the start of each session means a pairing key stolen from a phone cannot start a new session as either phone: this phone signs each start with its identity key, and the core refuses an unsigned start. A contact on a build from before signing cannot start a new session with this phone until it updates; sessions already running keep working. The weakest moment is a brand-new link: until its first ratcheted exchange, someone holding a stolen pairing key could still forge a message on it.

What is not built

Relaying messages through other people's phones is in the protocol and in the app as a setting that is off unless you turn it on, but it has not been measured on real hardware at real density and we do not present it as a working feature. NFC does not work peer to peer between iPhones and Android phones, so CHANNEL does not pair over it.

5. What we do not do

6. Export classification

CHANNEL uses only standard, published algorithms: X25519, Ed25519, ChaCha20-Poly1305, HKDF-SHA256, SHA-256, AES-256-GCM and PBKDF2-HMAC-SHA256, and MLS (RFC 9420) for formal groups, built from those same algorithms — the table in §1, in full. It defines no cryptography of its own. What the protocol specifies is how messages are routed, addressed and held, not how they are encrypted, and every primitive it names is public and widely implemented.

On that basis we answer Apple's encryption question as no non-exempt encryption (ITSAppUsesNonExemptEncryption is false in the shipped app). That is our good-faith reading: the app's encryption is standard and published, it exists to protect ordinary personal communication, and it is not special-purpose, not designed for any government or military use, and not a proprietary cryptographic method. We have tried to answer honestly without taking an over-broad view of what counts as non-exempt.

If a regulator or a reviewer reads the rules differently we would rather be told than be right, so the full protocol specification is published at /docs/protocol.html.

7. Questions

If you are a security researcher, an app reviewer, or simply someone who wants more detail than this page gives, the full protocol specification is at /docs/protocol.html. If you believe you have found a flaw, we want to hear it before anyone else does.

Contact: support@channelmessenger.net


Home · Privacy policy · User guide · Documentation

CHANNEL on X: @channelmsgr · Email: support@channelmessenger.net