All posts

ChaCha20-Poly1305 vs AES-256-GCM: Which Cipher Wins on Your Phone vs a Server?

Neither cipher is "stronger." AES-256-GCM flies on servers with AES-NI; ChaCha20-Poly1305 wins on phones and ARM boards without it, and is far harder to leak timing from. The honest, hardware-dependent answer, with XChaCha20's nonce as the sub-plot.

The short answer: it depends on the chip

Neither cipher is mathematically stronger. Both are 256-bit AEAD constructions with no practical break. AES-256-GCM wins on any CPU with AES-NI hardware — most servers, every Apple chip since the A7, most modern Android SoCs. ChaCha20-Poly1305 wins on hardware without AES acceleration, where it's also far harder to leak timing from. Pick by deployment target, not reputation.

What each cipher actually is

Both are authenticated encryption with associated data (AEAD): one operation that encrypts and produces a tag proving nobody tampered with the ciphertext. If the tag fails to verify, you get nothing back. Not garbage, not a partial read. Nothing. That's the property you want.

AES-256-GCM is the AES block cipher in counter mode with a Galois-field MAC bolted on for authentication. It's a NIST standard, defined in SP 800-38D, and that field-multiply step is exactly what Intel and ARM built dedicated instructions for.

ChaCha20-Poly1305 pairs Daniel Bernstein's ChaCha20 stream cipher with the Poly1305 MAC, standardized in RFC 8439. ChaCha20's entire inner loop is add, rotate, XOR — the "ARX" design, with no lookup tables and no field math anywhere. That one detail decides almost everything below.

Why does AES win on servers but lose on a cheap phone?

A modern server core runs AES-256-GCM through the AES-NI and PCLMULQDQ instructions. The round function and the GMAC multiply collapse into a handful of native ops, throughput lands in the gigabytes-per-second range per core, and with that hardware help AES-256-GCM can beat ChaCha20-Poly1305 by up to ~3x. That gap shows up consistently on modern silicon with AES acceleration — including Apple's M-series — where AES-256-GCM is comfortably the faster of the two on large blocks.

Take the hardware away and the picture inverts. On an ARM core with no AES extensions, software AES has to emulate the S-box with table lookups, while ChaCha20's add-rotate-XOR loop runs full speed on the general-purpose pipeline. In that software-only regime ChaCha20-Poly1305 is typically the faster cipher — often by well over half, and several times faster on small messages, depending on the platform. Cloudflare's well-known mobile work pointed the same way back in 2015: on phones with no AES acceleration, ChaCha20-Poly1305 was both quicker and easier on the battery.

ScenarioFaster cipherWhy
Server or desktop with AES-NIAES-256-GCM (up to ~3x)Dedicated round and carry-less-multiply instructions
Phone or ARM board, no AES extensionChaCha20-Poly1305 (usually faster)ARX ops run fast everywhere; software AES is table-bound
Pure-software build where side-channels matterChaCha20-Poly1305Constant-time by construction

The caveat that matters in 2026: most chips you'll ship to now have AES acceleration. Apple's A-series and M-series include it, and so do most mid-range and flagship Android SoCs. The software-AES penalty is real, but it's increasingly a story about old, cheap, or embedded hardware rather than the median user's phone.

The side-channel argument people skip

Speed isn't the only axis. A naive software AES looks up bytes in tables indexed by secret data, and how long those lookups take depends on what's sitting in the CPU cache. Bernstein demonstrated a remote cache-timing attack that recovered AES keys back in 2005. You can write constant-time AES in software with bitslicing, but it's genuinely hard and easy to get subtly wrong.

ChaCha20 sidesteps the whole class of bug. Add, rotate and XOR take the same time regardless of the data, so a correct implementation is constant-time almost for free. If you're targeting a platform with no AES hardware and you can't fully trust your own AES to be constant-time, ChaCha20-Poly1305 is the safer engineering call — not because AES is weak, but because your AES might leak.

Where does the nonce trap come in, and what does XChaCha20 fix?

Both ciphers share one sharp edge. Reuse a nonce with the same key and you can shred confidentiality, and in GCM's case the authentication along with it. Both default to a 96-bit nonce, and 96 bits isn't much if you're generating them at random. For exactly this reason, NIST's AES-GCM guidance (SP 800-38D) limits a single key to 232 invocations when nonces are chosen at random — a cap on how many messages you may safely send, set so the chance of ever repeating a random nonce stays negligible. Note what that number is and isn't: it's a message-count ceiling, not a "collision probability" you can quote as one-in-anything. Cross it and the risk of a catastrophic nonce repeat stops being negligible; stay under it and you're fine. RFC 8439's ChaCha20-Poly1305 carries the same 96-bit nonce and the same basic constraint. For a busy service, those ceilings arrive sooner than people expect.

Here's the sub-plot worth knowing. XChaCha20-Poly1305 extends the nonce to 192 bits by running an extra HChaCha20 step to derive a subkey. The practical effect is that you can pick nonces purely at random and essentially never think about collisions again — the draft spec puts the conservative ceiling at roughly 280 messages per key before a random-nonce repeat becomes a concern. There's no AES equivalent in standard use. If your design leans on random nonces at high volume, XChaCha20 removes a footgun that AES-GCM hands you with a warning label attached.

So which does beebeeb use, and why?

For file content, AES-256-GCM. The reason is the hardware argument above. Our crypto core runs as WASM in the browser and as native Rust in the CLI, and the overwhelming majority of devices that ever touch your files — the laptops and modern phones people actually own — ship AES-NI or its ARM equivalent. On that hardware AES-256-GCM is the fastest correct option, and it's a NIST primitive auditors already understand cold. We pair it with Argon2id for password-derived keys — the heavy key-stretching cost is paid when you log in or derive your master key, not on every file — and X25519 for sharing, and key material is zeroized after use. The full breakdown lives on our security page.

That's a deliberate choice, not a verdict against ChaCha. If we were shipping to a fleet of AES-less embedded boxes, the answer would flip. An independent audit of our implementation is planned, and the findings will be published when it's done — because "we use AES-256-GCM" is a claim you should be able to check, not take on faith. The engineering tradeoffs behind how we encrypt large files are covered on our features page.

"Encrypted" is a marketing checkbox. Which primitive, on which hardware, with what nonce discipline — that's the engineering commitment.

How to pick, without the hand-waving

Targeting servers, modern laptops, and recent phones? Use AES-256-GCM and let the silicon do the work. Targeting old or embedded hardware with no AES acceleration, or writing pure-software crypto where constant-time matters more than peak throughput? Reach for ChaCha20-Poly1305. Generating nonces at random under high volume? That's the case for XChaCha20-Poly1305 and its 192-bit nonce. None of these is about one cipher being "more secure" — at the 256-bit level they sit far beyond any feasible attack. They're about matching the construction to the chip and the threat model actually in front of you.

If you'd rather see this applied than argued,

Files only you can read

Beebeeb is end-to-end encrypted, zero-knowledge cloud storage — stored in Falkenstein, Germany, open source, with a 14-day free trial on every plan. Encryption happens on your device; we only ever hold ciphertext we can’t read.

Join the waitlist See pricing How the encryption works