I am reading DJ Bernstein's paper on the Poly1305-AES mac (https://cr.yp.to/mac/poly1305-20050329.pdf). I understand that AES is needed to provide the array s. In its paper on page 5 we can read:

reads AESk(n) from s[0], s[1], . . . , s[15]

I understand that n is a nonce and k is the secret key. What I am not sure about is which AES mode is used (ECB, CTR, GCM...) ? Is the nonce the message being passed to AES or is it a real nonce and thus we need to pass another message to AES ?

I am quite surprised that I cannot find any details about the AES mode in its paper. Is it because there is a default plain AES mode ?

FYI, I am using the mbed_tls crypto library, but I don't find any relevant example in their documentation.

  • 1
    $\begingroup$ You don't specifically need to use AES. Here is the spec for use with ChaCha. I suspect the AES mode is irrelevant as DJB in the paper you linked states "There is nothing special about AES here. One can replace AES with an arbitrary keyed function from an arbitrary set of nonces to 16-byte strings. This paper focuses on AES for concreteness." $\endgroup$
    – Modal Nest
    Commented Dec 2, 2020 at 20:20
  • $\begingroup$ @ModalNest: do I understand that I could select any AES mode, as long as it uses a nonce ? Also, is the nonce the message to be ciphered through AES or is the nonce an IV (or nonce-counter) used as a parameter for AES ? $\endgroup$
    – slaadvak
    Commented Dec 2, 2020 at 20:41
  • $\begingroup$ I would take on board what @kelalaka says. I suspect the choice is largely down to efficiency. Personally I would use what nacl uses (well just nacl itself). $\endgroup$
    – Modal Nest
    Commented Dec 2, 2020 at 20:47
  • $\begingroup$ When I look at Bernstein's reference implementation (poly1305aes-20050218) I see that he uses this custom function: aes_big(unsigned char out[16], const unsigned char k[16], const unsigned char n[16]). Then, out is being passed to poly1305 as the vector s. But again, I don't see a message being encrypted here, only a key and a nonce... Do he simply encrypt the nonce ? There is no comment in the code, it is not clear if he uses some "default" hardcoded message with k and n to generate s. $\endgroup$
    – slaadvak
    Commented Dec 2, 2020 at 21:20
  • $\begingroup$ Note that the Poly1305-AES cipher is a bit of a strange bird as you'd generally find that AES is best used with hardware acceleration which is usually not directly implemented for Poly1305. So if HW acceleration is present then AES-GCM may make more sense, as Intel did define instructions to help with GMAC. $\endgroup$
    – Maarten Bodewes
    Commented Dec 2, 2020 at 22:05

2 Answers 2


Yes, AES is just used as a 128 bit / 16 byte block cipher in this scheme. The paper specifies:

Poly1305-AES feeds each nonce $n$ through $AES_k$ to obtain the 16-byte string $AES_k(n)$.

There is no mention of AES without this key $k$ or nonce $n$. So, as far as AES - the block cipher - is concerned, $k$ is the key and the nonce $n$ is the data / message.

The reason that no mode-of-operation such as ECB / CBC is mentioned is that the specification uses the block cipher itself, without any mode. If you only have access to AES-ECB then you should use ECB without padding (or, if padding is always performed, just taking the first 16 bytes after feeding the nonce). You can use CBC with an IV using 16 zero valued bytes in a similar manner. Or you could use CTR with the nonce $n$ and an all zero plaintext of 16 bytes - probably makes most sense as CTR mode won't pad.

FYI the reason that you don't find an example in a TLS library is possibly that they use ChaCha20/Poly1305 where the ChaCha20 cipher is used instead of AES

From RFC 7905 section 1:

The variant of ChaCha used in this document has 20 rounds, a 96-bit nonce, and a 256-bit key; it is referred to as "ChaCha20". This is the conservative variant (with respect to security) of the ChaCha family and is described in [RFC7539].

From RFC 7539 section 2.8.1:

 otk = poly1305_key_gen(key, nonce)


     counter = 0
     block = chacha20_block(key,counter,nonce)
     return block[0..31]

So here chacha20_block is used instead of AES - they did say it was nothing special right? Note that the encryption then helpfully starts with counter 1 instead of zero, so it is a simple continuation of ChaCha20...

  • $\begingroup$ Thanks Maarten, this is exactly the information I was looking for! $\endgroup$
    – slaadvak
    Commented Dec 2, 2020 at 21:46
  • 1
    $\begingroup$ Well, I can always add more useful information :) $\endgroup$
    – Maarten Bodewes
    Commented Dec 2, 2020 at 21:56
  • $\begingroup$ Thanks. mbed_tls is not only a tls library. With that library, you can do auth, cipher, hash... it is similar to what you would find in libsodium or in monocypher. So they provide poly1305 implementation, but they don't provide a turn-key solution, so you have to generate the secret 's' yourself, using AES or ChaCha20. Which library are you using for your snippets in your answer ? $\endgroup$
    – slaadvak
    Commented Dec 2, 2020 at 22:00
  • 1
    $\begingroup$ None, that's the pseudo code in the specifications, i.e. the RFC's. $\endgroup$
    – Maarten Bodewes
    Commented Dec 2, 2020 at 22:01

In Java, you would do something like ...

byte[] key = ... 16 byte AES key 'k'
byte[] nonce = .... 16 byte nonce 'n'

Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); // key is 16 bytes - 128 bits - thus AES-128
cipher.init(Cipher.ENCRYPT_MODE, keySpec);

// Compute encrypted nonce
byte[] encryptedNonce = new byte[16];
cipher.doFinal(nonce, 0, nonce.length, encryptedNonce, 0);

See the cipher block in the setKey() method of https://github.com/bcgit/bc-java/blob/f11f5d333d921c0b773a8e2ec4037723897662e2/core/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java#L25

  • 1
    $\begingroup$ Why would you bring up Java? There's nothing about Poly1305, or AES, or ChaCha that's language-specific, and this is why I'm commenting. $\endgroup$
    – DannyNiu
    Commented Oct 14, 2021 at 7:27
  • $\begingroup$ Great comment DannyNiu. Thank you for the criticism. The OP asked: What I am not sure about is which AES mode is used (ECB, CTR, GCM...) ? Is the nonce the message being passed to AES or is it a real nonce and thus we need to pass another message to AES ? $\endgroup$ Commented Oct 15, 2021 at 10:13
  • $\begingroup$ The java code shows the ECB mode being used and it also shows the nonce being encrypted and also links to an actual Poly1305 AES Impl where they can clearly see what code could look like that passes the tests. Forgive me though for such a stupid irrelevant answer $\endgroup$ Commented Oct 15, 2021 at 10:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.