XChaCha: eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305Paragon Initiative EnterprisesUnited Statessecurity@paragonie.com
Internet
(No Working Group)encryptionAEADcryptographysecurityauthenticated encryptionThe 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 helps for long running TLS connections.
This also 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, misuse resistant cipher constructions come at a cost in performance
as they must necessarily make two passes over the message to be encrypted. An
alternative strategy can significantly reduce the chance of accidental nonce
reuse 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,
xsecretbox,
Tink,
and in Go's crypto/chacha20poly1305 library.
Similarly, Google's HPolyC implements
XChaCha12.
LibreSSL
has already implemented XChaCha20-Poly1305.
Note that the construction we're building upon uses the IETF's ChaCha20 (96-bit nonce),
not Bernstein's ChaCha20 (64-bit nonce).
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^80 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. Instead, the block counter
is replaced by the first 32 bits of the nonce.
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, in little
endian, 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 .
Note that, with the AEAD mode, the initial block counter is set to 1
instead of 0, since the first block is used to derive the one-time
Poly1305 key.
The encryption function can also be used for decryption, since the
keystream generated by ChaCha20 is just mixed with the plaintext
using bitwise XOR.
The security of the XChaCha construction depends on both the security
of the ChaCha stream cipher and the HChaCha intermediary step, for
reasons explained in the XSalsa20 paper
(which our XChaCha construction is derived from).
Given that the 20-round ChaCha stream cipher (ChaCha20) is believed
to be at least as secure as Salsa20, our only relevant security
consideration involves HChaCha20.
In the XSalsa20 paper, when HSalsa20 is defined, the author states,
"The indices 0, 5, 10, 15, 6, 7, 8, 9 here were not chosen arbitrarily;
the choice is important for the security proof later in this paper."
In the analysis of Theorem 3.1 from the same paper (which covers generalized
cascades), the author further states: "Note that this bound is affected
less by the insecurity of H than by the insecurity of S."
This means that the security of HSalsa20 affects the security of
XSalsa20 less than Salsa20 does, and the same applies to any generalized
cascade following a similar construction.
However, we want to be sure that HChaCha is secure even if it's less
security-affecting than ChaCha (which we already believe to be secure).
In Salsa20, the indices 0, 5, 10, 15 were populated with constants, while
the indices 6, 7, 8, and 9 were populated by the nonce. The security proof
for HSalsa20 relies on the definition of a function Q (specified in Theorem
3.3 of the paper) that provides two critical properties:
Q(i) is a public computation of H(i) and S(i).Q(i) is a public computation of uniform random strings from uniform random
strings.Thus, HSalsa20 uses the same indices as the public inputs (constant + nonce)
for its final output.
The reliance on public computation for the security proof makes sense, and
can be applied to ChaCha with a slight tweak.
ChaCha is a slightly different construction than Salsa20: The constants occupy
the indices at 0, 1, 2, 3. Meanwhile, the nonce populates indices 12, 13, 14, 15.
Consequently, we can extract a public computation from ChaCha20 by selecting
these indices from HChaCha20's final state as the HChaCha20 output, and the
same security proof can be used.
Therefore, if the argument that makes HSalsa20 secure is valid, then it also
applies to HChaCha for the corresponding output indices.
If the 20-round HChaCha (HChaCha20) is secure, and the 20-round ChaCha20 is
secure, then XChaCha20 is also secure.
This document defines a new stream cipher ("XChaCha20", see ) and a
new AEAD cipher construction ("XChaCha20-Poly1305", see ).
A new entry in the "Authenticated Encryption with Associated Data (AEAD) Parameters"
registry with the name "AEAD_XCHACHA20_POLY1305" should be assigned.
Plaintext:
AAD:
Key:
IV:
32-bit fixed-common part:
Poly1305 Key:
Ciphertext:
Tag:
Note: This is for the XChaCha20 stream cipher itself, not the AEAD
construction.
Counter: 0
Plaintext:
Key:
IV:
Keystream:
Ciphertext:
Counter: 1
Plaintext:
Key:
IV:
Keystream:
Ciphertext:
For the sake of usability, the above test vectors have been
reproduced in a format more readily usable by implementors.
All values below are hex-encoded, as per RFC 4648 .
Plaintext:
AAD:
Key:
IV:
32-bit fixed-common part:
Poly1305 Key:
Ciphertext:
Tag:
Counter: 0
Plaintext:
Key:
IV:
Keystream:
Ciphertext:
Counter: 1
Plaintext:
Key:
IV:
Keystream:
Ciphertext: