Skip to main content

2.6 Generating the Poly1305 Key Using ChaCha20

2.6 Generating the Poly1305 Key Using ChaCha20

As said in Section 2.5, it is acceptable to generate the one-time Poly1305 key pseudorandomly. This section defines such a method.

To generate such a key pair (r,s), we will use the ChaCha20 block function described in Section 2.3. This assumes that we have a 256-bit session key specifically for the Message Authentication Code (MAC) function. Any document that specifies the use of Poly1305 as a MAC algorithm for some protocol MUST specify that 256 bits are allocated for the integrity key. Note that in the AEAD construction defined in Section 2.8, the same key is used for encryption and key generation.

The method is to call the block function with the following parameters:

  • The 256-bit session integrity key is used as the ChaCha20 key.

  • The block counter is set to zero.

  • The protocol will specify a 96-bit or 64-bit nonce. This MUST be unique per invocation with the same key, so it MUST NOT be randomly generated. A counter is a good way to implement this, but other methods, such as a Linear Feedback Shift Register (LFSR) are also acceptable. ChaCha20 as specified here requires a 96-bit nonce. So if the provided nonce is only 64-bit, then the first 32 bits of the nonce will be set to a constant number. This will usually be zero, but for protocols with multiple senders it may be different for each sender, but SHOULD be the same for all invocations of the function with the same key by a particular sender.

After running the block function, we have a 512-bit state. We take the first 256 bits of the serialized state, and use those as the one-time Poly1305 key: the first 128 bits are clamped and form "r", while the next 128 bits become "s". The other 256 bits are discarded.

Note that while many protocols have provisions for a nonce for encryption algorithms (often called Initialization Vectors, or IVs), they usually don't have such a provision for the MAC function. In that case, the per-invocation nonce will have to come from somewhere else, such as a message counter.

2.6.1 Poly1305 Key Generation in Pseudocode

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

2.6.2 Poly1305 Key Generation Test Vector

For this example, we'll set:

Key:

000  80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f  ................
016 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f ................

Nonce:

000  00 00 00 00 00 01 02 03 04 05 06 07              ............

The ChaCha state setup with key, nonce, and block counter zero:

      61707865  3320646e  79622d32  6b206574
83828180 87868584 8b8a8988 8f8e8d8c
93929190 97969594 9b9a9998 9f9e9d9c
00000000 00000000 03020100 07060504

The ChaCha state after 20 rounds:

      8ba0d58a  cc815f90  27405081  7194b24a
37b633a8 a50dfde3 e2b8db08 46a6d1fd
7da03782 9183a233 148ad271 b46773d1
3cc1875a 8607def1 ca5c3086 7085eb87

Output bytes:

000  8a d5 a0 8b 90 5f 81 cc 81 50 40 27 4a b2 94 71  ....._...P@'J..q
016 a8 33 b6 37 e3 fd 0d a5 08 db b8 e2 fd d1 a6 46 .3.7...........F

And that output is also the 32-byte one-time key used for Poly1305.