Can your staff read our notes?
That is the question in the support inbox of a shared care journal, an app where a family and a visiting nurse track an elderly man's care: doses given, blood-pressure readings, a photo of a new rash. Marta, his daughter, asks it before writing anything more personal. For most apps the honest answer is that they could, if they wanted to.
Her phone reaches the API over TLS, which ends at the company's servers; the database encrypts its disks and its sensitive columns with keys from a KMS. Each layer is unlocked by a key the company's own services hold, because they read the notes to serve them. Who can read is decided by who holds the key; when the answer is your own services, Secrets management & encryption covers doing it well.
End-to-end encryption (E2E) gives the other answer: a note is encrypted on the device that writes it, decrypted only on the devices that read it, and only those devices hold the keys that open it. The server still routes and stores every note, as bytes it cannot read. The cost starts with a plain question: which devices are the devices that read it?
A key pair for every device, not every person
Each device creates its own key pair when the app is installed: a private key that is meant never to leave it, and a public key anyone may have. Whoever holds a device's public key can send something only that device can read. (In practice two devices use their public keys to agree on shared secret keys, and those encrypt the notes.) That encryption is authenticated: a note altered in transit or in storage fails its check on the receiving device and is rejected. Devices publish their public keys to a key directory on the server, under their account and a device id. The server never sees a private key.
The journal has three people and five devices: Marta's phone and laptop, her brother Jonas's phone and tablet, and the nurse Inês's work phone. Marta writes a note on her phone:
- Marta's phone asks the directory for the device keys of everyone in the journal and gets four: her own laptop, Jonas's two devices and Inês's phone.
- The phone encrypts the note four times, once for each device.
- The phone sends the four ciphertexts to the server, each addressed to a device id.
- Each device decrypts its own copy when it arrives.
In between, the server delivers and holds those copies as it would any message, the mechanics of Worked design: a realtime chat; what E2E changes is that every copy it holds, including the one waiting for Inês's switched-off phone, is ciphertext. Marta's laptop is on the list because otherwise it would never show what she wrote from her phone: the server has no copy it can open for her. This per-device fan-out makes the sender's work grow with the devices on the other side.
One ciphertext per device. The server delivers what it can and holds Inês's copy, unable to decrypt any of them.
Writing to a phone that is switched off
Inês's phone, off for the night, cannot take part in a handshake. Protocols in the Signal family solve that with prekeys: each device uploads to the directory, in advance, public keys made for starting sessions, some of them signed with its long-term identity key, the key pair it made at install. Marta's phone combines Inês's prekeys with keys of its own and arrives at a secret Inês's phone will compute when it wakes.
After that, the Double Ratchet, the other half of the Signal protocol, derives a new key for each message and deletes the old ones, so a key taken from a phone today does not decrypt notes copied off the network or the server last month, except notes whose keys a device still holds for late or out-of-order delivery; how many and for how long depends on the implementation. That is forward secrecy, and the fresh key exchanges the ratchet mixes in can also let a session heal after a leak, once the attacker is off the device and not tampering with the exchanges that follow. It protects old ciphertext, not old notes on the phone: a thief holding Marta's unlocked phone reads whatever history the app shows.
One encryption per device is cheap for five devices; a care home's journal with 40 staff on 90 devices would make every note 89 of them. Group schemes such as sender keys have each device send the group, over its pairwise sessions, a key of its own from which each message's key is derived, encrypt each note once, and send a new one to the members who remain whenever someone leaves, since the leaver holds the old ones. MLS (Messaging Layer Security, IETF RFC 9420) is the standard built for groups of up to thousands of members.
The directory could lie
All of this trusts the directory. A dishonest server, or an attacker who controls it, could add a key of its own or swap one for Inês's, then decrypt, read and re-encrypt each note to her real key. This man-in-the-middle breaks no cipher.
The defence is to check keys outside the server. Each pair of people has a safety number (some apps say security code): a fingerprint derived from the identity keys on both sides, shown as digits and a QR code. When Marta and Inês meet at her father's house, they scan each other's codes; a substituted key would not match. Each device has its own identity key, so Marta either checks each of Inês's devices, or a newer one is vouched for by a device she already checked, with a signature her app can verify instead of taking the directory's word. Few people do this, so the app also remembers each contact's identity key and says so when it changes.
A change is usually a new phone, occasionally an attack, and the app cannot tell which. Warn loudly on every reinstall and people learn to tap through, so an ordinary contact gets a quiet line, Inês's security code changed, and a verified one can get more, such as holding the next note until Marta confirms. Key transparency goes further: the directory publishes its entries in an append-only log that clients and auditors can check, so showing different keys to different people leaves evidence.
Jonas gets a new phone
In a careful design one of his existing devices approves the new phone, so the directory alone cannot add a device; notes written after that are encrypted to it too. Last year's notes were encrypted to his old devices, and the server either deleted those ciphertexts after delivery or holds copies only the old keys open; it cannot re-encrypt what it cannot read. That leaves three designs:
- Start empty. The new phone shows notes from the day it joined.
- Transfer from a device he still has. His tablet sends the history to the new phone, encrypted between the two devices.
- Restore an encrypted backup. The device encrypts the backup with a key derived from a passphrase or recovery key only Jonas holds; a key derived from a passphrase is only as strong as the passphrase against offline guessing, which a random recovery key avoids. The company stores it and cannot open it, so if Jonas forgets the passphrase or loses the recovery key, nobody can open the backup, the company included.
A second nurse joining the journal raises the same question; someone whose device holds the earlier notes would have to re-encrypt them for her, and whether they should is a product decision the design has to state.
A photo and a push that say nothing
A photo is too large to encrypt once per device, so Marta's phone encrypts it once with a fresh random key, uploads the ciphertext to object storage (Object storage & blobs), and puts the file's location, that key and a hash of the encrypted file inside the note; each device downloads the same blob, checks the hash and decrypts. The push that wakes Inês's phone travels through Apple's or Google's push service, which sees its payload, so it carries only a wake-up or an opaque message id; the app fetches the ciphertext, decrypts it and builds the notification on the phone, or, where the platform gives it no time to, shows a plain New note in the journal. Sending pushes reliably is the ground of Notifications & transactional messaging.
The photo is stored once, as ciphertext; its key travels inside the note, and the push carries only an id. The gateway is left out, and so is the queue that keeps the push off the send path.
What the server can no longer do
- Search. The server cannot index text it cannot read. Each device indexes its own decrypted notes, so a search covers only the history that device holds.
- Previews. A server fetching a link to preview it would see the link, so the sending device builds previews and thumbnails and sends them inside the note.
- Spam and abuse detection on content. What remains is behaviour, such as rate limits and new accounts writing to many strangers, and user reports, in which the reporting device chooses to send decrypted messages to the company.
- Support and analytics on content. Nobody at the company can read a note to settle a dispute, recover a lost history or analyse what people write.
What the server still sees is metadata: which accounts share a journal, how many devices each has, when each note was sent and from which IP address, how large it was. End-to-end encryption hides none of that, and notes at three in the morning several nights running say something on their own.
Where the ends are
End-to-end encryption trusts the ends. Malware on Marta's phone, or someone holding it unlocked, reads everything the app shows, and since the app holds the private keys, a malicious update could copy notes out without touching a cipher; some teams answer with published client code and reproducible builds.
The End-to-End Encrypted Messaging Challenge asks for this system as a messenger in at most 17 nodes: draw the key directory as its own service, encrypt to every device, and answer on the diagram what history a new phone sees, how the key-change warning reads and which features you moved to the device or dropped.