RFC 7539: ChaCha20 and Poly1305 for IETF Protocols

2026-05-23

RFC: RFC 7539

Published: May 2015

Authors: Yoav Nir (Check Point), Adam Langley (Google)

If you've opened an HTTPS connection from a phone in the last decade, or set up a WireGuard tunnel, you've almost certainly used the constructions standardized in RFC 7539. It's the IETF's adoption of Daniel J. Bernstein's ChaCha20 stream cipher and Poly1305 message authenticator, glued into an AEAD (Authenticated Encryption with Associated Data) construction. The RFC was written explicitly to give the IETF a vetted, public-domain alternative to AES-GCM.

The problem. By 2013, AES-GCM had become the default AEAD on the web. It's excellent when your CPU has AES-NI instructions — Intel/AMD desktops, server-class chips. But on mobile ARM cores without AES acceleration, AES-GCM was painfully slow and, worse, vulnerable to cache-timing side channels in naive software implementations. GCM's GHASH also depends on carryless multiplication (PCLMULQDQ); without it, performance cratered. Google measured this directly while serving billions of mobile clients and wanted a cipher that was fast and constant-time on every CPU.

The design choices. ChaCha20 is an ARX cipher — built only from Add, Rotate, XOR on 32-bit words. No S-boxes, no lookup tables, no data-dependent branches. That makes it inherently constant-time and trivially portable. It's a refinement of Bernstein's earlier Salsa20 (a 2008 eSTREAM finalist), with diffusion improvements that made it faster and arguably more conservative cryptographically. Twenty rounds is the standard variant; the security margin is generous.

Poly1305 is a Wegman–Carter one-time MAC over the prime field 2^130 − 5. It produces a 16-byte tag from a 32-byte one-time key. The "one-time" part is critical: reuse a Poly1305 key and an attacker can recover it from two tags. RFC 7539's AEAD construction therefore derives the Poly1305 key by running ChaCha20 with a counter of 0 and using the first 32 bytes of the keystream, then encrypts the plaintext starting at counter 1. The MAC covers AAD, ciphertext, and their lengths — with length fields padded to defeat the classic (AAD="A", CT="B") vs (AAD="AB", CT="") ambiguity.

What's quirky. The RFC reads less like a typical IETF spec and more like a tutorial. It includes worked numerical examples for every step: the ChaCha20 quarter-round, full block, Poly1305 clamping, and an end-to-end AEAD encryption with Sunscreen lyrics from Baz Luhrmann as the plaintext. That decision was deliberate — Langley and Nir wanted implementers to be able to verify their code against intermediate values, because subtle bugs in Poly1305's modular arithmetic (especially the r clamp: r &= 0x0ffffffc0ffffffc0ffffffc0fffffff) had bitten earlier implementations.

Why it matters today.

RFC 7539 was obsoleted by RFC 8439 in 2018, which fixed errata and clarified edge cases (notably around AAD length encoding), but the substance is identical. The cipher itself has held up remarkably well: no meaningful cryptanalytic progress against the full 20-round ChaCha20 in over fifteen years, and the constant-time-by-construction design has aged better than nearly any other symmetric primitive of its era.

Why it matters: RFC 7539 standardized the cipher that keeps your phone's TLS fast and side-channel-safe — and quietly became the cryptographic backbone of WireGuard, QUIC, and modern SSH.

All newsletters