diffie-hellman mac x25519 xsalsa20
Updated Fri, 20 May 2022 20:46:55 GMT

Composition of X25519+XSalsa20+Poly1305

In a correct implementation of X25519+XSalsa20+Poly1305, I think I have the right understanding in saying that the Poly1305 message authentication code is a function of the secret key + plaintext.

My question is, on the recipient side, with such a construction, is there a need to supply some extra secret to check the validity of the MAC/Tag?

I guess my question stems from using other primitives such as HMAC SHA-256, where to verify the authenticated hash you need an additional secret to be shared.

In the case of X25519+XSalsa20+Poly1305, is the only secret required to decrypt and verify simply the result of the X25519 ECDH key agreement? i.e. there is no additional MAC secret?


Poly1305 itself has the requirement that its keys can only ever be used to generate a tag for a single message. That means that when Poly1305-AES (or another Poly1305-based authenticated encryption algorithm) is used as intended, the Poly1305 authentication key will be different for each message even if a key is reused.

However, the various Poly1305-based authenticated encryption algorithms (let's say Poly1305-*) support key reuse as long as the same nonce is not reused for a given key. The nonce is a non-secret (single use) value, so it can be sent alongside the ciphertext.

Poly1305-* generates a new Poly1305 (authentication) key for every new message. It does this by using the (authenticated encryption) key and the per-message nonce to derive the single use Poly1305 key. As long as both the sender and receiver use the same key and same nonce, it is possible for both people to derive an agreed-upon per-message Poly1305 (authentication) key.

In Poly1305-AES, that key is basically derived by extracting the first 16 bytes of an AES CTR-mode key stream. Subsequent keystream blocks are XORed with the plaintext. Note that bits used for the per-message Poly1305 (authentication) key and the bits used for message encryption are non-overlapping portions of the key stream. Because the keystream is pseudorandom, the per-message derived Poly1305 are expected to be unique.

Because this is a safe way for the sender and receiver to agree upon a per-message key, there is no need for an API to expose the per-message key to the programmer using the API. They just see parameters for one key and for the nonce.

(An API may even go further and abstract away the nonce, randomly generating one every time the encryption function is called and silently concatenating it with the ciphertext and MAC tag. The corresponding decryption function also could silently read the nonce from its expected location in the combined nonce/ciphertext/tag string, never exposing anything but the shared key, combined ciphertext, and plaintext to the programmer.)

Comments (1)

  • +0 – Exceptionally clear answer. Thank you very much! — Jan 17, 2020 at 07:46