XChaCha: eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305Paragon Initiative EnterprisesUnited Statessecurity@paragonie.com
Internet
(No Working Group)securitytokenThe eXtended-nonce ChaCha cipher construction (XChaCha) allows for
ChaCha-based ciphersuites to accept a 192-bit nonce with similar guarantees
to the original construction, except with a much lower probability of nonce
misuse occurring. This enables XChaCha constructions to be stateless, while
retaining the same security assumptions as ChaCha.
This document defines XChaCha20, which uses HChaCha20 to convert the
key and part of the nonce into a subkey, which is in turn used with the
remainder of the nonce with ChaCha20 to generate a pseudorandom keystream
(e.g. for message encryption).
This document also defines AEAD_XChaCha20_Poly1305, a variant of
that utilizes the XChaCha20 construction in place of ChaCha20.
AEAD constructions (Authenticated Encryption with Associated Data) allow
for message confidentiality to be assured even in the presence of adaptive
chosen-ciphertext attacks, but they're known to be
brittle to nonce-misuse conditions.
Several nonce misuse resistant cipher constructions have been proposed over
the years, including AES-SIV (), AES-GCM-SIV,
and several CAESAR candidates.
However, a more straightforward strategy can prevent nonce misuse conditions
in environments where a large number of messages are encrypted. Simply use a
large enough nonce such that applications can generate them randomly for each
message and the probability of a collision remains low.
To this end, we propose a solution that is already implemented in many software
projects that extends the nonce of ChaCha20 to 192 bits and uses it to build an
AEAD construction.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
"SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
and "OPTIONAL" in this document are to be interpreted as described in
RFC 2119 .
XChaCha20-Poly1305 is a variant of the ChaCha20-Poly1305 AEAD construction as
defined in that uses a 192-bit nonce instead of a 96-bit nonce.
The algorithm for XChaCha20-Poly1305 is as follows:
Calculate a subkey from the first 16 bytes of the nonce and the key, using
HChaCha20 ().Use the subkey and remaining 8 bytes of the nonce (prefixed with 4 NUL
bytes) with AEAD_CHACHA20_POLY1305 from as normal. The definition
for XChaCha20 is given in .XChaCha20-Poly1305 implementations already exist in
WireGuard,
libsodium,
Monocypher,
xsecretbox,
and in Go's crypto/chacha20poly1305 library.
Similarly, Google's HPolyC implements
XChaCha12-Poly1305.
The nonce used by the original ChaCha20-Poly1305 is too short to safely use with
random strings for long-lived keys. XChaCha20-Poly1305 does not have this
restriction.
By generating a subkey from a 128-bit nonce and the key, a reuse of only the
latter 64 bits of the nonce isn't security-affecting, since the key (and thus,
keystream) will be different. Additionally a re-use of only the first 128 bits
of the nonce isn't security-affecting, as the nonce derived from the latter 64
bits is different.
Assuming a secure random number generator, random 192-bit nonces should experience
a single collision (with probability 50%) after roughly 2^96 messages
(approximately 7.2998163e+28). A more conservative threshold (2^-32 chance of
collision) still allows for 2^64 messages to be sent under a single key.
Therefore, with XChaCha20-Poly1305, users can safely generate a random 192-bit
nonce for each message and not worry about nonce-reuse vulnerabilities.
As long as ChaCha20-Poly1305 is a secure AEAD cipher and ChaCha is a secure
pseudorandom function (PRF), XChaCha20-Poly1305 is secure.
HChaCha20 is an intermediary step towards XChaCha20 based on the
construction and security proof used to create
XSalsa20, an extended-nonce
Salsa20 variant used in NaCl.
HChaCha20 is initialized the same way as the ChaCha cipher, except that
HChaCha20 uses a 128-bit nonce and has no counter.
Consider the two figures below, where each non-whitespace character represents
one nibble of information about the ChaCha states (all numbers little-endian):
After initialization, proceed through the ChaCha rounds as usual.
Once the 20 ChaCha rounds have been completed, the first 128 bits and last 128
bits of the ChaCha state (both little-endian) are concatenated, and this 256-bit
subkey is returned.
Key = 00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f.
The key is a sequence of octets with no particular structure before we
copy it into the HChaCha state.Nonce = (00:00:00:09:00:00:00:4a:00:00:00:00:31:41:59:27)After setting up the HChaCha state, it looks like this:
After running 20 rounds (10 column rounds interleaved with 10
"diagonal rounds"), the HChaCha state looks like this:
HChaCha20 will then return only the first and last rows, resulting
in the following 256-bit key:
XChaCha20 can be constructed from an existing ChaCha20 implementation
and HChaCha20. All one needs to do is:
Pass the key and the first 16 bytes of the 24-byte nonce to
HChaCha20 to obtain the subkey.Use the subkey and remaining 8 byte nonce with ChaCha20 as normal
(prefixed by 4 NUL bytes, since specifies a 12-byte
nonce).XChaCha20 is a stream cipher and offers no integrity guarantees without
being combined with a MAC algorithm (e.g. Poly1305).
The same HChaCha20 subkey derivation can also be used in the context
of an AEAD_ChaCha20_Poly1305 implementation to create
AEAD_XChaCha20_Poly1305, as described in .
Plaintext:
AAD:
Key:
IV:
32-bit fixed-common part:
Poly1305 Key:
Ciphertext:
Tag:
c0:87:59:24:c1:c7:98:79:47:de:af:d8:78:0a:cf:49