How do I tack on "additional data" to libsodium's public-key authenticated encryption? I note that libsodium provides AEAD when using symmetric cryptography.

And yet, under section 8 (Public-key cryptography) there are no public-key methods described which allow for additional data (AD) to be included.

Keeping in mind cryptographic best practices, is there an elegant way to essentially add the feature of additional data to a public key cryptographic AE method like crypto_aead_chacha20poly1305_encrypt?  That is, suppose that the libsodium building blocks remain as they are.  How do I add additional information sent in the clear that becomes part of the authenticated message?

And I'm curious if the absence of such a method now is for any particular reason.
Internally, libsodium public key encryption uses the same primitives as the (nonAEAD) secret key authenticated encryption, namely XSalsa20 and Poly1305. NaCl, which libsodium is based on, does not have an AEAD interface at all. Instead, libsodium added it from a TLS draft. There is no similar reference for public key AEAD use of these primitives, since in TLS they are expected to be used with the negotiated secret key. That is my guess as to the main reason it does not exist in libsodium.

As an aside, the use case for public key AEAD seems a bit thin overall. Usually the additional data in AEAD is used for protocol information that is not secret but must be tied to a particular message. E.g. in TLS it includes the sequence number and compression details. However, if you have a protocol where multiple messages are sent, you do not really want to use public key encryption for each message, but rather a session key and symmetric encryption.

There are many ways you could go about constructing your own:


Simplest would be to just include the additional data in the message to be encrypted. That is wasteful if you also need to send it in the clear, of course, and you can only verify it after decryption. You can avoid duplicating long data by including only a hash of the data in the message.
Alternatively, you could sign the encrypted message + additional data. That requires a signing key-pair, the public key of which is known to the receiver. It also adds quite a bit of overhead. However, it does allow verification of the additional data before decryption.
Finally, you could negotiate a symmetric key and use the AEAD cipher already in libsodium. Simply generating a random symmetric key and encrypting it with public key authenticated encryption would work, but there are more complex ideas too, depending on what kind of security you need.




Note: the currently included AEAD cipher based on the draft only uses an eight byte nonce, which is too short to be safely generated randomly. A later version of libsodium will include the updated version with a longer nonce.