Skip to main content
1 of 5
Maarten Bodewes
  • 94.5k
  • 13
  • 165
  • 319

If we look into the source code of the JDK 11 where this feature was introduced, we can see it is based on RFC 7539, not on RFC 8439. However, a quick look showed that they may be compatible none-the-less.

  • although the Poly1305 MAC is defined using AES, the AEAD cipher is not;
  • the AEAD construction is defined in chapter 2.8 and points to 2.6 which defines generating a Poly1305 key from the nonce using ChaCha20 block encrypt.

So the nonce is taken directly as parameter, and it is not generated by the application at all. However, the Poly1305 key is generated from this nonce. Note that a MAC does not require an IV or nonce otherwise, only a key. For Poly1305 that key needs to be unique, which is why it is calculated from the nonce of the entire AEAD cipher.


So the authentication tag is protected using a ChaCha20 block encrypt rather than AES:

    authenticator = new Poly1305();

    // Derive the Poly1305 key from the starting state
    byte[] serializedKey = new byte[KEYSTREAM_SIZE];
    chaCha20Block(startState, 0, serializedKey);

    authenticator.engineInit(new SecretKeySpec(serializedKey, 0, 32,
            authAlgName), null);

In other words, the ChaCha20Cipher class which implements the ChaCha20-Poly1305 AEAD cipher (using the Poly1305 authenticator class) doesn't mention or reference AES or any block cipher anywhere.


Note that I've previously mentioned (in a deleted answer) that stream ciphers can generally not be used to perform this kind of key derivation from the nonce. However, ChaCha20 operates on blocks underneath, which makes these kind of operation possible.

Maarten Bodewes
  • 94.5k
  • 13
  • 165
  • 319