I am new to cryptography, I have used OpenSSL and its aes-256-cfb cipher before to do stream encryption, which works great. Now I am going to try libsodium, since it's light and its APIs look concise, but I can't get it working.

I tried its XChaCha20 stream cipher, but it only has the crypto_stream_xchacha20_xor and crypto_stream_xchacha20_xor_ic functions, I can easily encrypt and decrypt messages when the message lengths appear in pairs, like encrypting 20 bytes, then decrypting 20 bytes, this works fine. but it will fail if encrypting 20 bytes, then decrypting 10 bytes and decrypting 10 more bytes. The latter case is what I want, I am implementing a proxy, I would like to read random length (i.e. not in blocks and no boundaries) of data from one TCP connection, encrypt and stream the data through another TCP connection, the other end of the connection reads random length of the encrypted data and decrypts it.

For what I want, xoring my data wouldn't work, since there's no context object like OpenSSL's EVP_CIPHER_CTX and no information like how many bytes have been encrypted/decrypted is kept, this looks weird to me, if it doesn't support this kind of stream mode, why is it called a stream cipher?

My question: Is it possible to do what I want using libsodium, if so, how?


closed as off-topic by fkraiem, Ella Rose, e-sushi Aug 4 '18 at 10:09

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Programming questions are off-topic even if you are writing or debugging cryptographic code. Unless your question is specifically about how the cryptographic algorithm, protocol or side-channel (mitigation) works, you should look into asking on Stack Overflow instead." – fkraiem, Ella Rose, e-sushi
If this question can be reworded to fit the rules in the help center, please edit the question.


libsodium has an API dedicated to stream encryption: crypto_secretstream, which is fully documented here: https://download.libsodium.org/doc/secret-key_cryptography/secretstream.html

Using simply crypto_stream_* or OpenSSL aes-256-cfb would be completely insecure. Without any authentication tags, the stream can be tampered with, without any ways to detect that it happened.

crypto_secretstream lets you encrypt and decrypt a sequence of variable-length messages, and prevents tampering, reordering and truncation.

However, if 50 bytes, then 20 bytes are encrypted, you must decrypt 50 bytes, then 20 bytes as well, in this order.

If you are reading data from a TCP connection, you should accumulate it into a fixed-size buffer, and once that buffer is full or you have reached the end of the stream, encrypt or decrypt its content. This will also improve performance and minimize the overhead of authentication tags over encrypting the outcome of ever single read() call.


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