Engineering

Choosing XChaCha20-Poly1305 over AES-GCM

Nonce-misuse resistance, performance on mobile, and why a 192-bit nonce lets us stop worrying about a whole class of bugs.

AJAkshay J.·May 21, 2026·13 min read
Choosing XChaCha20-Poly1305 over AES-GCM

Key takeaways

  • XChaCha20-Poly1305 uses a 192-bit nonce, making collisions practically impossible without coordination
  • ChaCha20 outperforms hardware-AES on mobile SoCs that lack dedicated AES acceleration
  • Poly1305 authentication runs in constant time, closing a class of timing side-channels
  • Nonce-misuse resistance means a repeated nonce leaks nothing beyond the repeated message itself

When we picked a cipher for Inktally's document encryption, the obvious choice was AES-GCM — hardware-accelerated, widely audited, the default for everyone from TLS to Signal. We chose XChaCha20-Poly1305 instead. This is the engineering reasoning.

The nonce problem with AES-GCM

AES-GCM requires a unique nonce for every encryption operation. The nonce can be as short as 96 bits (12 bytes). If you encrypt two different plaintexts with the same key and the same nonce, the encryption is catastrophically broken — an attacker can XOR the two ciphertexts and immediately get the XOR of the two plaintexts, plus forge authentication tags.

With a 96-bit nonce, if you generate nonces randomly, birthday-bound probability puts your first collision at around 2^48 operations — roughly 281 trillion encryptions. That sounds comfortable until you consider that mobile apps generate a fresh nonce per message, per document version, per key wrapping operation, across millions of users. The math gets uncomfortable faster than you'd expect.

What XChaCha20-Poly1305 fixes

XChaCha20-Poly1305 uses a 192-bit nonce. At that size, birthday-bound collision probability is negligible even at internet scale. We can safely generate nonces randomly without a collision-resistant counter or a global sequence number — both of which require coordination that is hard to implement correctly in a distributed system.

The “X” prefix indicates the extended-nonce variant of ChaCha20, specifically designed to make random nonce generation safe. The underlying stream cipher (ChaCha20) plus the Poly1305 MAC gives us authenticated encryption with associated data (AEAD) — same category as AES-GCM, same security model, larger nonce.

Implementation detail

We use libsodium's crypto_secretstream_xchacha20poly1305 for streaming large documents and crypto_aead_xchacha20poly1305_ietf for short sealed boxes. Both are audited, formally verified implementations — we do not implement the cipher ourselves.

Performance on constrained devices

AES-GCM has hardware acceleration (AES-NI) on most modern CPUs, but not on all mobile processors, and not in older WebAssembly environments. ChaCha20 is software-fast — it was designed to be competitive on processors without AES acceleration, achieving performance comparable to AES-NI on systems that lack it, and slightly slower on systems that have it.

For Inktally's use case, the bottleneck is almost always network and storage I/O, not cipher throughput. The small CPU difference is irrelevant in practice.

See this in practice.

Your vault is encrypted before it leaves your device. Inktally never sees your keys.

Try Inktally free

The decision

XChaCha20-Poly1305 gives us nonce-misuse resistance, random nonce safety, and cross-platform software performance. We give up a small amount of CPU performance on AES-NI-equipped desktops, and we accept a cipher that is slightly less familiar to auditors than AES-GCM (though ChaCha20 is extensively studied).

For a client-side encrypted application where mistakes in nonce management would be catastrophic and undetectable, that trade is an easy one to make.

Share this article

Common questions

Questions about choosing xchacha20-poly1305 over aes-gcm

01

Questions about choosing xchacha20-poly1305 over aes-gcm

No — AES-GCM is secure when used correctly. The risk is that correct use requires careful nonce management. XChaCha20-Poly1305 is nonce-misuse resistant, meaning it tolerates the category of mistakes that make AES-GCM dangerous.

Get the security writing in your inbox.

No marketing. One email when something worth reading publishes.

No tracking pixels. Unsubscribe any time.