I'm interested in using libsodium to encrypt the data stream between a client and server application. The data consists of a (semi-infinite) sequence of bi-directional messages of varying length that are transmitted over a socket. The application is an existing C++ application to which encryption is being retrofitted.
Reading the libsodium documentation, https://libsodium.gitbook.io/doc/secret-key_cryptography/secretstream, I am left with the following questions:
Rekeying: in the section about rekeying (https://libsodium.gitbook.io/doc/secret-key_cryptography/secretstream#rekeying), I'm told rekeying happens transparently. Great! But earlier (https://libsodium.gitbook.io/doc/secret-key_cryptography/secretstream#encryption) it says that the size of an encrypted message is always the same as the size of the plaintext message plus a constant. It seems to me that rekeying would require additional messages to be transmitted (or at least additional space in existing messages), and thus take up more space than a standard message. Is the information under "encryption" (i.e. that the size of an encrypted message is known in advance) correct? How does rekeying work, if it can be done without apparently taking up any space in the message stream?
The header: in both decryption examples (https://libsodium.gitbook.io/doc/secret-key_cryptography/secretstream#decryption, https://libsodium.gitbook.io/doc/secret-key_cryptography/secretstream#file-encryption-example-code), the header is transported from the encrypting function to the decrypting function. Does this mean I also have to exchange a pair of messages just to bring the header state up to date between both parties? Or can I regenerate the header from scratch with the information I already have available? In the example code, both the 'state' and 'header' variables are uninitialized, and the key is available to both client and server, so perhaps I can generate it on both sides as well and skip sending it as a separate message? Or is there additional cryptographic information in the header that needs to be transported as well?
Message boundaries: the documentation says that "Note that tags are encrypted; encrypted streams do not reveal any information about sequence boundaries" (https://libsodium.gitbook.io/doc/secret-key_cryptography/secretstream#usage). However, the decryption examples take the message size as an input argument, so clearly this is something that must be known before decryption can start. I suppose I can send my messages as a sequence of pairs of messages, with a fixed-length message containing the size of the next variable length message, and both being encrypted, but is there a better solution?
Bonus question... Libsodium seems like a good candidate for tackling this problem. I also looked at OpenSSL but it seems to require considerably more manual steps to set up and maintain an encrypted socket. Are there any alternatives that I have missed, that do the job with a minimum of fuss?