Insight

How We Encrypt Emails

How black.com encrypts your email: passkey-derived ML-KEM-1024 and ML-DSA-87 keys, AES-256-GCM, what SMTP exposes, and end-to-end encryption between users.

Patrick Brunner, Simon Lindner

In Plaintext

  1. Your encryption keys are created on your device from your passkey. We only ever receive your public keys.
  2. Mail between black.com users is end-to-end encrypted. Our servers only store ciphertext they can't open.
  3. Mail to and from Gmail or any other provider has to be readable for a moment while SMTP hands it over. We encrypt it as soon as it arrives, and your outgoing mail stays encrypted until you hit send.
  4. Your mail is protected with ML-KEM-1024 and AES-256-GCM, NIST standards chosen to hold up against quantum computers.
  5. For now you still have to trust us to hand out the right public keys. Key pinning arrives in Q1 2027.

Every email you store with black.com is encrypted so that only keys created on your device, from your individual passkey, can open it. We never see those keys.

There is a big exception to how private that makes your mail. It's called SMTP. Mail to and from Gmail, Outlook or any other provider has to be briefly readable while crossing over, both to our servers and to the other provider's.

This article walks you through every step:

  • How your passkey creates your encryption keys
  • What happens when you email someone on Gmail
  • How mail between two black.com users stays end-to-end encrypted
  • Which algorithms we use
  • Why no single email provider can close the SMTP gap on its own

First a little confession though. Back in 2024, a thread about us on the Privacy Guides forum made a fair point: we publicly said little about how our encryption works. Our team was so focused on building that we didn't properly communicate what seemed clear to us. So here it is, in full. Everything below describes black.com v2 (November 2026).

Three things are true for every email in your black.com inbox:

  1. Your private keys never leave your device.
    They are derived from your passkey through the WebAuthn PRF extension. We only ever receive your public keys.
  2. Mail between black.com users is end-to-end encrypted.
    It is encrypted and signed on the sender's device and decrypted on the recipient's. Our servers store ciphertext they can't open.
  3. Mail from other providers is encrypted the moment it arrives.
    And mail you send to other providers stays encrypted until the moment you hit send.

Here are the building blocks, before we go through them one by one:

Job What we use Standard
Signing in Passkeys W3C WebAuthn Level 3
The secret your keys come from PRF extension (hmac-secret under the hood) WebAuthn Level 3, FIDO CTAP2
Sharing keys ML-KEM-1024 NIST FIPS 203
Encrypting content AES-256-GCM NIST SP 800-38D
Signatures ML-DSA-87 NIST FIPS 204

How Do Passkeys Create Your Encryption Keys?

Your passkey essentially does two jobs. It signs you in, and it produces the secret your encryption keys are made from.

How Do Passkeys Sign You In?

A passkey is a key pair. The private half lives with your passkey provider (iCloud Keychain, Google Password Manager, 1Password or a hardware security key) and never leaves that place. We exclusively store the public half. (Which also means the account behind your passkey provider deserves a strong lock of its own.)

When you sign in, our server sends a fresh challenge, your device signs it, and we then confirm the signature. Because a passkey is bound to our domain, a phishing site on a look-alike domain gets nothing usable. There is nothing worth stealing on our side either. It's a public key after all.

What Is the WebAuthn PRF Extension?

Passkeys can do one more thing that most websites never use. Next to its signing key, a passkey can hold a second secret that is not used for signing and never handed to websites or apps. FIDO's CTAP2 calls it hmac-secret. WebAuthn exposes it to apps as the prf extension, an abbreviation for pseudo-random function.

Our app hands the passkey an input, prf_input. The browser or operating system first hashes it together with a fixed label, which keeps web values separate from other uses of the same secret (like an operating system login). Then the authenticator runs it through HMAC with the credential's secret:

prf_output = HMAC-SHA256(cred_secret, SHA-256("WebAuthn PRF" || 0x00 || prf_input))

The result, prf_output, is 32 bytes. Three properties make it a good seed for encryption keys:

  1. It's deterministic.
    The same passkey and the same input give the same 32 bytes, on every device your passkey syncs to. (One subtlety should be noted: CTAP2 keeps separate secrets for sign-ins with and without user verification, so that setting has to stay the same too.)
  2. It's unique.
    A different passkey gives a completely unrelated output.
  3. It stays on your device.
    The authenticator returns it to our app on your device. It is never sent to us.

And we're not the only ones who think so. Signal founder Moxie Marlinspike uses passkey PRF to make end-to-end encryption in Confer "feel as simple as logging in."

prf became part of a finished standard on August 25, 2026, when WebAuthn Level 3 became a W3C Recommendation. Support took a while (Windows Hello only started returning PRF values with a February 2026 update, according to Corbado's tracking). Today it works with iCloud Keychain, Google Password Manager, Windows Hello and 1Password, while some password managers still don't return it. That matters: black.com needs a passkey provider that supports the WebAuthn PRF extension. Without it, you can't create an account or sign in.

(Moxie again, in January 2026: "Unfortunately Bitwarden has chosen not to support passkey prf. Other password managers like 1password do though!" Source.)

How Are Encryption Keys Derived from a Passkey?

Your device turns prf_output into two seeds, one per algorithm, and each seed into a key pair:

kem_seed = HKDF-SHA512(prf_output, "ml-kem-1", 64) dsa_seed = HKDF-SHA512(prf_output, "ml-dsa-1", 32) (kem_public_key, kem_private_key) = ML-KEM-1024.KeyGen(kem_seed) (dsa_public_key, dsa_private_key) = ML-DSA-87.KeyGen(dsa_seed)

(The quoted strings are HKDF's domain-separation labels, and the numbers are output lengths in bytes.)

The lengths aren't arbitrary. ML-KEM's key generation takes exactly two 32-byte seeds (FIPS 203 calls them d and z), and ML-DSA's takes one (ξ). The seed fully determines the key pair, so your iPhone and Mac compute the same keys without your email keys ever being synced. Nothing to sync, nothing to leak. The trade-off: because your keys come straight from one passkey's PRF output, an account has exactly one passkey, and moving to a new passkey or provider means re-wrapping the key of every email. We explain how that works in the last section.

Your device then sends us kem_public_key and dsa_public_key. That's everything we get: the two keys other people need to encrypt for you and to check your signatures. prf_output, both seeds and both private keys stay on your device.

Diagram. Inside a box labeled Your device: a passkey produces prf_output (32 bytes) through the prf extension; the 24 recovery words back up the same value. HKDF-SHA512 turns prf_output into kem_seed (64 bytes) and dsa_seed (32 bytes), which become an ML-KEM-1024 key pair and an ML-DSA-87 key pair whose private keys stay on the device. Only kem_public_key and dsa_public_key cross the box's edge to black.com servers, which store only the two public keys.
Figure 1: From one passkey to two key pairs. Everything inside the box stays on your device. Only your two public keys cross its edge.

What Happens If You Lose Your Passkey?

If you lose your passkey, you lose your keys. And your passkey doesn't really belong to you. It lives with Apple, Google and others. Switching providers has gotten easier (Apple added passkey export in iOS 26), but whether the PRF secret comes along for the ride is up to each provider. We didn't want your mailbox to depend on that.

Tim Cappalli, one of the editors of the WebAuthn spec, puts the risk bluntly: using a sign-in credential for encryption makes the "blast radius" of losing it "immeasurably larger." He's right. That's exactly why we built a second way in.

So every account comes with a 24-word recovery phrase. It encodes exactly the 32 bytes your passkey produces at sign-in (prf_output), and nothing else: a written-down copy of the seed all your keys come from. It is crucial that you write it down once and keep it somewhere safe, so that you can re-derive the same key pairs without your passkey or its provider. Treat it like the key to your mailbox: whoever has it can read everything in it.

There's also a second, simpler way back in: SMS recovery. If you lose your passkey and your 24 words, we can send a code to your phone number and you set up a new passkey. That gets you back into your account. It doesn't get you back into your old emails, because those are encrypted for keys that came from your old passkey. Only the old passkey or your 24 words can open them. We can help you get back in. We can't help you read what you had.

That trade-off is deliberate. Hardcore privacy people will say a phone number has no place near an encrypted inbox, and we understand why. But for most people, being locked out of their account forever is the far bigger risk. And someone who gets hold of your phone number still can't open a single old email.

What Happens If Your Phone Is Lost or Taken?

No encryption helps if someone forces you to unlock your phone. xkcd made that point in 2009 with a $5 wrench.

Short of that, it depends on the state your phone is in. Our apps keep your seed in the iPhone Keychain or the Android Keystore, protected by your phone's hardware. After a restart, nobody can read it until you unlock the phone once. After that, it stays available until the next restart, and that's the state forensic tools like Cellebrite and GrayKey try to break into over a cable. If your phone is unlocked, whoever holds it can simply open the app. In the browser, only your computer's login protects the seed, one more reason we recommend the apps.

Three things help. On iPhone, long-press the black.com app and choose "Require Face ID" (on Android, use Private space or your phone's app lock). Restart your phone if it might be taken. And if it's gone, sign it out under Settings > Active Sessions: the app deletes your keys the next time it goes online.

Why Use Passkeys Instead of Passwords for Encryption?

A password-derived key would work too. Until v2, that's what we used, and most encrypted email providers still do. That being said, we moved away from it for two reasons in particular:

  1. A password-derived key is only as strong as the password.
    In a password-based design, your private key is stored on the server, encrypted with a key derived from your password, so you can fetch it on a new device. If that encrypted blob ever leaks, an attacker can guess passwords against it offline, as fast as their hardware allows. A slow hash like Argon2id raises the cost per guess but it doesn't stop the guessing. A PRF output is 256 bits from a secret that never existed on our servers. There is nothing to guess.
  2. Passwords get lost.
    With zero-access encryption, a forgotten password means a locked mailbox. (Passkeys can get lost too. That's why you'll have your 24 words.)

A quick word for everyone who was with us before v2 (thank you, by the way). Your old mail comes along, but it has to move from your old v1 keys to your new ones. That move happens once, on our servers. When you set up your passkey, your app hands over your old v1 RSA private key. A server job then opens every draft, email and attachment, locks it again with AES-256-GCM, wraps its key for your new ML-KEM-1024 public key, and deletes your v1 key when it's done.

How Is an Email Encrypted When You Send It to Gmail?

Mail between providers travels over SMTP, and the provider at the other end has to be able to read what arrives. Therefore, an email to Gmail stays encrypted until you hit send, and an email from Gmail gets encrypted the moment it reaches us. Only in that short window in between, while SMTP hands the email over, can our mail servers and Gmail's read it.

What Happens When You Hit Send?

Say Alice (alice@black.com) writes to Charlie (charlie@gmail.com).

  1. While Alice types, her app encrypts the draft with a fresh, random msg_key (AES-256-GCM) and stores it with us, with msg_key wrapped for her own kem_public_key_alice. Every autosave is ciphertext. We can't read her drafts.
  2. When she hits send, her app hands our outbound mail service msg_key. Only this one: not her private key, and not the key of any other email.
  3. The outbound service then decrypts the email, turns it into a standard MIME message, signs it with DKIM so Gmail can verify it really comes from us, and delivers it to Gmail's mail server over SMTP. Delivery always uses TLS: if Gmail's server didn't offer encryption, the email wouldn't go out. Like most mail servers today, ours doesn't yet check the receiving server's certificate. That's what MTA-STS and DANE are for, which we cover below.
  4. Our servers keep msg_key only until our mail server accepts the message (for a scheduled email, until its send time), then delete it. Our mail server keeps the readable message for at most one day while it retries delivery. Alice's Sent copy stays exactly as it was: ciphertext that only she can open.

From here on, Charlie's copy is Gmail's to protect. We can't encrypt someone else's inbox.

What Happens When an Email Arrives from Gmail?

Now Charlie replies.

  1. Gmail's server connects to ours over SMTP and hands over the email. We use TLS whenever the other side offers it, but we don't require it yet.
  2. Our inbound service checks it for spam by looking at the sender, not the content: SPF, DKIM and DMARC, public blocklists (Spamhaus sees the connecting server's IP and domain, never the email) and your own blocklist. Nothing reads the body.
  3. It generates a fresh msg_key, encrypts the email with AES-256-GCM and wraps msg_key for kem_public_key_alice with ML-KEM-1024.
  4. The plaintext is discarded. From now on, only Alice's devices can open the email.

Normally, steps 1 to 3 are the only time our systems hold the email in plaintext. (If our mail server can't hand an email over to the app, it keeps the raw message until a retry succeeds, for at most 30 days.) This is what zero-access encryption means: we see the email once and never again.

Filippo Valsorda made the case against this model back in 2020, aimed at Proton: a provider that ingests inbound mail in plaintext shouldn't simply call that end-to-end encryption. The critique applies to every zero-access provider, including us. That's why we only use the term for mail between black.com users.

Diagram with two lanes. Sending to Gmail: Alice's device encrypts the draft with a fresh msg_key and hands black.com outbound that one msg_key; outbound decrypts, builds MIME, signs with DKIM and delivers over SMTP with TLS required to Gmail, where Charlie's copy follows Gmail's rules. Receiving from Gmail: Gmail sends Charlie's reply over SMTP with TLS if offered; black.com inbound checks the sender for spam, encrypts for Alice and stores ciphertext only in Alice's mailbox. The two black.com boxes are highlighted as readable by black.com servers.
Figure 2: Mail to and from Gmail. In both directions, our servers handle plaintext only where SMTP requires it.

Why Can't SMTP Be End-to-End Encrypted?

SMTP is probably older than you. RFC 821 defined it in August 1982, back when the internet was just a few hundred university and research machines whose admins all more or less knew each other. Back then, nobody was worried about strangers reading the mail. So SMTP does one job: it carries a message from one server to the next, like a postal worker handing a postcard down the line. It has no idea what a public key is.

Encryption for the connection itself arrived 17 years later, with STARTTLS (RFC 2487, 1999, today RFC 3207). It encrypts each hop between two servers, but every server along the way still gets the full message. STARTTLS is polite to a fault. When one server offers encryption, and the other side doesn't take the offer, both shrug and carry on in plaintext. An attacker between them only has to delete that one offer. A 2015 study of Gmail's traffic found seven countries where more than 20% of inbound Gmail messages arrived in cleartext because of network attackers. MTA-STS (2018) and DANE (2015) close that downgrade. We don't use either yet. And neither changes the fact that the servers can read the mail.

(And it's not always an attacker. In 2015, Hanno Böck noticed Cisco advertising STARTTLS stripping as a security feature.)

End-to-end encryption needs something at the other end: a public key we can look up, and software that can decrypt with it. For charlie@gmail.com, neither exists. There is no key for Charlie we could find, and his inbox couldn't open an ML-KEM ciphertext if we sent one.

PGP and S/MIME have tried to bolt this onto email since the 1990s. However, they only work when both sides set them up, and almost nobody does. In 2015, PGP's own inventor, Phil Zimmermann, told a researcher he couldn't decrypt an encrypted message because he didn't "have a version of PGP that runs on any of my devices." As he told Motherboard: "The irony is not lost on me." OpenPGP even got post-quantum algorithms in June 2026 (RFC 9980), but they only help if Charlie has a post-quantum key. He doesn't.

Believe us, if we could fix SMTP from our side, we would have done it by now. But it's the language every mail server on Earth speaks. Changing it means getting Gmail, Outlook and millions of other servers to change at the same time. Nobody gets to do that alone. So we do the next best thing: we keep that readable moment as short as we possibly can, and only on the one hop where SMTP leaves us no choice.

If you take anything with you from this article, it should be this: end-to-end encryption needs two ends. We can only build ours.

That's why black.com has a free plan. Price should never be the reason the other end is missing.

Which Parts of an Email Can't Be Encrypted over SMTP?

For mail to and from other providers, once it is stored with us:

  • Encrypted with your keys: your drafts, and the subject, body and attachments of every email.
  • Readable to our servers, because SMTP needs it: sender and recipient addresses (SMTP routes by the envelope, MAIL FROM and RCPT TO), plus when each email arrived and how big it is.
  • Readable while crossing the SMTP hop: the whole message, as described above.
  • Out of our hands: the copy at the other provider. Charlie's Gmail inbox follows Gmail's rules, not ours.

How Does End-to-End Encrypted Email Work between black.com Users?

When Alice writes to Bob (bob@black.com), nothing ever has to be decrypted on our side. Her app encrypts and signs the email for Bob before it leaves her device, and only Bob's devices can open it.

  1. Alice's app fetches Bob's public keys, kem_public_key_bob and dsa_public_key_bob, from our key directory.
  2. It generates a fresh, random msg_key and encrypts each field of the email (subject, body, attachments) with AES-256-GCM, each with its own fresh 12-byte nonce.
  3. It wraps msg_key twice with ML-KEM-1024: once for Bob (msg_key_bob) and once for Alice herself (msg_key_alice), that way the email shows up in her Sent folder.
  4. It signs the encrypted email and the wrapped keys with dsa_private_key_alice (ML-DSA-87).
  5. Our servers store and deliver the ciphertext, the wrapped keys and the signature. None of it is readable to us: we hold no key that opens it.
  6. Bob's app verifies Alice's signature with dsa_public_key_alice, unwraps msg_key_bob with kem_private_key_bob and decrypts.
Diagram. Step 1: black.com servers give Alice's device Bob's public keys. Steps 2 to 4: Alice's device encrypts with msg_key, wraps it for Bob and Alice and signs with ML-DSA-87. Step 5: black.com servers store and deliver ciphertext only and hold no key to open it. Step 6: Bob's device verifies the signature, unwraps msg_key_bob and decrypts the email. Only Alice's and Bob's devices are highlighted as the places where the email is readable.
Figure 3: Mail between two black.com users. The email is readable on exactly two devices. Everything in between holds ciphertext.

Compare that to the Gmail case and one step is gone: no app ever hands us a msg_key. That one missing step is the difference between zero-access and end-to-end encryption.

And when Bob writes back, the same thing happens the other way around. His reply is locked for Alice before it reaches us. We just pass it along. Not even for a second do we see what's inside.

The signature matters as much as the encryption. It proves the email really comes from Alice's keys, and that nobody (us included) changed a single byte on the way.

In step 1, Alice's app trusts that kem_public_key_bob really belongs to Bob. A compromised server could hand out a key of its own instead. (The same goes for Bob, who checks Alice's signature with a public key he also got from us.) We'll come back to how we're closing that gap at the end of this article.

Which Email Metadata Can't Be Encrypted?

Encryption hides what you write. It doesn't hide that you wrote. Even between two black.com users, our servers need a few things to deliver mail:

  • Who writes to whom. We have to know whose mailbox a message goes into.
  • When, and how big. Every server knows when it received something and how many bytes it was.
  • Your IP address when you connect. Every server you talk to sees it.
  • Your public keys. These are public by design. That's what makes encrypting for you possible.

Your content is encrypted end-to-end: the subject, the body and every attachment. (With PGP, the subject line traditionally travels in plaintext. Not here.) Your folder and label names are still stored in plaintext today; encrypting them is coming soon. The metadata listed above stays readable to us.

Side by side, this is what our servers can read:

What our servers can read black.com to black.com To or from other providers
Body and attachments Never Only while crossing SMTP
Subject Never Only while crossing SMTP
Sender and recipient addresses Yes Yes
Time and size Yes Yes
Your IP address when you connect Yes Yes

Which Encryption Algorithms Does black.com Use?

Three algorithms do the heavy lifting: ML-KEM-1024 shares the keys, AES-256-GCM locks the content itself, and ML-DSA-87 signs every email. If you are wondering why we picked these and not something else, this is the part for you. At the end, we put all three together in one real example.

What Are ML-KEM-1024 and ML-DSA-87?

Both have been NIST standards since August 13, 2024: ML-KEM in FIPS 203, ML-DSA in FIPS 204. They grew out of CRYSTALS-Kyber and CRYSTALS-Dilithium, two winners of a public competition NIST started back in 2016, where cryptographers around the world spent years trying to break every entry. Both rest on module lattice problems, and so far nobody, with or without a quantum computer, has found an efficient way to solve them.

  • ML-KEM is a key encapsulation mechanism. Anyone with your kem_public_key can create a fresh 32-byte shared secret, plus a ciphertext that only your kem_private_key can turn back into that same secret. We use the secret to wrap message keys.
  • ML-DSA is a signature scheme. Your dsa_private_key signs, and anyone with your dsa_public_key can verify. Every email you send to another black.com user is signed with it.

Each comes in three sizes. We use the largest:

Parameter set Public key Private key Ciphertext or signature NIST category
ML-KEM-1024 1,568 bytes 64-byte seed (3,168 bytes expanded) 1,568 bytes 5
ML-DSA-87 2,592 bytes 32-byte seed (4,896 bytes expanded) 4,627 bytes 5

Category 5 means breaking the scheme should take at least as much effort as a brute-force search for an AES-256 key. It's the highest category NIST defines, and it's the same choice the NSA made for its CNSA 2.0 suite, which requires ML-KEM-1024, ML-DSA-87 and AES-256.

So why not the smaller ML-KEM-768, the size Chrome and Firefox use for TLS? Because an email isn't a website visit. Going up a size costs 384 extra bytes per public key and 480 per ciphertext. When you open a website, every extra byte makes the page a tiny bit slower, millions of times a day. An email doesn't care about a few hundred bytes. What it does care about is time: it sits in your mailbox for years, and that's what "harvest now, decrypt later" attackers are counting on. These hackers collect today and crack whenever they have access to enough quantum compute. That is why we'd rather spend those bytes on extra margin.

We're in good company with that question. In 2024, Daniel J. Bernstein, who designed X25519, wondered why Google saw Kyber-768 as low-risk enough not to move up to Kyber-1024, for a "384 bytes larger key, 480 bytes larger ciphertext."

Why not a hybrid with X25519, the way TLS and the new OpenPGP standard do it? To keep it simple. We use ML-KEM-1024 on its own, with no classical half. Every extra layer is more code, more formats and more room for mistakes, and ML-KEM-1024 is the same choice CNSA 2.0 makes.

Serious cryptographers land on both sides of this question, and we believe that's healthy for a young standard. Cryptographer JP Aumasson summed it up in August 2026: hybrid is "what's getting deployed and recommended in most official guidelines," and "those who'll choose nonhybrid will have their reasons not necessarily unwise."

Why Is AES-256-GCM the Gold Standard for Symmetric Encryption?

ML-KEM doesn't encrypt data at all. It produces shared secrets, and we use those to protect one 32-byte msg_key per email. The email itself is encrypted with AES-256-GCM.

  • AES (FIPS 197, 2001) is the most analyzed block cipher in existence, and every modern phone and laptop has hardware instructions for it. We use it with 256-bit keys.
  • GCM (NIST SP 800-38D) turns it into authenticated encryption. Besides keeping the content secret, it attaches a 16-byte tag that detects any change. Flip a single bit and decryption fails.
  • Against quantum computers, Grover's algorithm at best halves the effective key length. AES-256 keeps around 128 bits of security, which is still far out of reach.

GCM does have one well-known weak spot. A nonce is a number that may only ever be used once with the same key (hence the name). If it is used twice, GCM breaks badly. We made sure that can't happen by design:

  1. Every email gets its own msg_key
  2. Every encryption a fresh random nonce
  3. Every wrap a fresh ML-KEM shared secret.

No key ever protects more than one email, so there is nothing to reuse.

"Gold standard" doesn't mean flawless. As Filippo Valsorda points out, GCM also doesn't commit to its key, so a ciphertext can in principle be crafted to decrypt under two different keys. That's a limit GCM doesn't solve on its own.

What Does an End-to-End Encrypted Email Look Like, Step by Step?

Here is the whole flow in one place, the way our apps do it today. Names ending in _alice or _bob say whose key it is. The ML-KEM shared secret is already a uniformly random 32-byte value, so we use it directly as the AES-256 key that wraps msg_key.

On Alice's device:

# 1. Encrypt every field of email e1 (subject, body, attachments) msg_key = random(32) for each field: nonce = random(12) ciphertext = AES-256-GCM.Encrypt(msg_key, nonce, field) # 2. Wrap msg_key for Bob shared_secret_bob, kem_ciphertext_bob = ML-KEM-1024.Encaps(kem_public_key_bob) nonce_bob = random(12) msg_key_bob = AES-256-GCM.Encrypt(shared_secret_bob, nonce_bob, msg_key) # 3. Same for Alice's own copy in Sent # (kem_public_key_alice -> kem_ciphertext_alice, nonce_alice, msg_key_alice) # 4. Sign the encrypted email and Bob's wrapped key signature_alice = ML-DSA-87.Sign(dsa_private_key_alice, ciphertext || kem_ciphertext_bob || nonce_bob || msg_key_bob)

On Bob's device:

# 1. Check Alice's signature first, stop if it fails ML-DSA-87.Verify(dsa_public_key_alice, ciphertext || kem_ciphertext_bob || nonce_bob || msg_key_bob, signature_alice) # 2. Unwrap msg_key, then decrypt each field shared_secret_bob = ML-KEM-1024.Decaps(kem_private_key_bob, kem_ciphertext_bob) msg_key = AES-256-GCM.Decrypt(shared_secret_bob, nonce_bob, msg_key_bob) field = AES-256-GCM.Decrypt(msg_key, nonce, ciphertext)

What we store for this email, on top of the encrypted email itself:

Part Size
nonce and GCM tag, per encrypted field 28 bytes
Wrap for Bob (kem_ciphertext_bob, nonce_bob, msg_key_bob) 1,628 bytes
Wrap for Alice (same layout) 1,628 bytes
signature_alice (ML-DSA-87) 4,627 bytes
Total for a one-field email to Bob 7,911 bytes

About 8 KB per email, plus 28 bytes for each extra field and 1,628 bytes for every additional recipient. That's the real price of post-quantum encryption. Not speed, just a few kilobytes.

How Does Search Work in an End-to-End Encrypted Inbox?

Search runs in your app on your own device (web, iOS or Android), not on our servers. Your search terms never reach us. It sounds simple, but it is one of the hardest problems we have worked on.

Gmail can quickly search on its servers because it can read your mail. We can't, by design. That leaves three options:

  1. Search on the server, over encrypted data.
    Searchable encryption lets a server match encrypted queries against an encrypted index. The problem here is leakage: the server learns which emails match which query, and how often. In realistic settings, that's enough to recover queries and even content, as Cash, Grubbs, Perry and Ristenpart showed in 2015. And a server often knows more than you'd think. If a million people receive the same newsletter, its words are no secret, and they make a pretty good codebook for decoding the rest.
  2. Heavier cryptography.
    Fully homomorphic encryption or private information retrieval can hide even which emails match. For an inbox with tens of thousands of emails, they are still too slow and too expensive.
  3. Search on the device.
    Download, decrypt, index locally. The server learns nothing new. The cost lands on your device instead.

Matthew Green, who teaches cryptography at Johns Hopkins, put option 1 best: "The entire field of searchable encryption seems like a contest to see how much information you can leak."

We chose option 3, the same principle Proton uses for its message content search. Our version works differently for the two kinds of mail:

  • Mail to and from other providers. When an email arrives or is sent, our servers hold its plaintext for that one SMTP moment anyway. In that moment they turn the subject, body and attachment names into a short list of words, in any language: lowercased, each word only once ("invoice" ten times is stored once), cut to 16 characters ("Datenschutzgrundverordnung" becomes "datenschutzgrund"), single letters dropped, at most 5 KB per email and about 1 KB on average. The list is encrypted with that email's own msg_key and stored next to it. After that, we can't read it either.
  • Mail between black.com users. We never see that plaintext, so there is no list. Your app decrypts the subject first, then the attachment names, then the body, and stops as soon as all your words are found.
  • When you search, your app splits your query the same way, downloads up to 5,000 encrypted lists at a time (newest first), decrypts them 50 at a time in parallel and checks whether all your words appear. Parts of words count, so "voice" finds "invoice". It stops after 100 matching conversations, and "Search deeper" keeps going further back.

Does building those word lists leak anything? Not beyond what SMTP already forces on us. The list is made in the same moment our servers see the email anyway, and it's encrypted before it's stored. After that, we can't read it, and we never learn which words you search for.

The trade-offs: because there's no real index, the further back you search, the longer it will take you. You also can't search for exact phrases ("meeting Friday" finds any email with both words). And text beyond the 5 KB limit isn't searchable, and neither is the text inside a PDF.

What's Next for black.com Encryption?

Three things are on our list. One makes your keys portable, one removes the biggest remaining reason to trust us, and one takes end-to-end encryption beyond our own domain.

What Happens When You Rotate Your Passkey?

Today your keys come from one passkey. Switching to a new passkey means a new prf_output, which means new key pairs. And every email in your mailbox has its msg_key wrapped for your old kem_public_key.

So rotation is a bit like moving house with a very large key ring. Your device unwraps each msg_key with the old private key and wraps it again for the new public key. The emails themselves don't change. Only their wraps do.

The math is the easy part. On a single ordinary CPU core, unwrapping and re-wrapping one key takes about a tenth of a millisecond, so even 100,000 emails need only seconds of compute. The bytes are the hard part: 100,000 wraps at 1,628 bytes each add up to about 163 MB that have to come down to your device and go back up. Reliably, and without leaving your mailbox half-migrated if your phone dies at 60%.

How Do You Know a Public Key Really Belongs to Your Contact?

Remember the caveat from earlier: when Alice's app asks for Bob's public key, it trusts our answer. Today, that is one of the places where you still have to trust black.com. We don't think you should have to.

To be precise: before every send, your app fetches each recipient's current public key from our servers and doesn't warn you if it has changed. So for now, you are trusting us to hand out the right keys. Two more things expert readers will check, so we'll say them first. On the web, the encryption code itself is delivered by our servers every time you open the app. And our code isn't open source and hasn't been independently audited yet.

Starting in Q1 2027, our apps will pin keys. The first time your app sees a contact's public key, it remembers it. If our server ever hands out a different key for the same address, your app notices and tells you, instead of quietly encrypting for a key that might not be Bob's.

Pinning is a first step, not the last one. It protects every email after the first one (security people call this trust on first use). The industry's longer-term answer is verifiable key directories, which WhatsApp started rolling out in 2023. The goal is the same either way: you shouldn't have to trust us at all. We're not there yet, and we would rather say so.

Can End-to-End Encryption Work across Email Providers?

Everything in this article stops at our own domain. The moment Alice writes to Gmail, SMTP takes over, and there is no key on the other side we could encrypt for. We spent a whole section on why that can't be fixed from one side.

So we're building something both sides can speak: a way for any two email providers to exchange end-to-end encrypted, signed, post-quantum mail, with the same guarantees two black.com users get today. In other words, a full replacement for SMTP. It doesn't need every mail server on Earth to switch at once, just two providers that both speak it. It's a big claim and we'll back it up soon.

That's our system, as of v2. If you spot a mistake in this article or a weakness in the design, let us know about it: tell us on X at @blackcom. And if there's one part you'd like us to go deeper on (passkeys, ML-KEM or the search index), tell us there too. It might be the next article.

Sources and Further Reading

Passkeys and PRF

Lost or stolen devices

Post-quantum and symmetric cryptography

SMTP and email security

Search and key directories

About us

On X