How to use stream cipher to encrypt TCP data?

466 views Asked by At

i try to use chacha20 encryption in my network software but i encounter a problem

if i encrypt 4 bytes data: 0x01 0x02 0x03 0x04 on server

and get the ciphertext: 0xd2 0xd3 0xc4 0xd5, then send it to client

the client may receive <= 4bytes at a time

provided that client only recv 0xd2 0xd3 at first ,

it can decrypt data properly and get plaintext 0x01 0x02

but when client recv the last 2 bytes 0xc4 0xd5

it seems that the data can't be decrypt using the same nonce and key

so is there a way to solve the problem

adding length data as prefix before sending is a solution,but it's weird because i am using stream cipher.

2

There are 2 answers

4
Frank Denis On

ChaCha20 generates a stream, using the key and the nonce. Let (S0, S1, S2, S3) the first bytes of the stream, and (M0, M1, M2, M3) the first 4 bytes of your message.

The ciphertext will be computed as (M0⊕S0, M1⊕S1, M2⊕S2, M3⊕S3). This is if you have M0...M3 readily available.

If you encrypt (M0, M1) then (M2, M3) using the same key and nonce, you will end up with (M0⊕S0, M1⊕S1) and (M2⊕S0, M3⊕S1). Which cannot be decrypted using (C0⊕S0, C1⊕S1, C2⊕S2, C3⊕S3).

Even worse, since S0 and S1 have been reused with different messages, an attacker can recover them knowing any message.

The easiest thing to do in order to avoid this is to buffer the data until you reach the block size, and then encrypt the whole block, instead of trying to encrypt partial blocks.

0
Maarten Bodewes On

Instead of restarting the ChaCha20 cipher instance (or, more generically, context) you should keep it alive.

Most cryptographic API's will allow you to perform piecemeal encryption / decryption. That usually means calling an update method for the first part and second part, generally followed by a final method when the end of the plaintext / ciphertext is detected. Depending on the API you should expect output for each of these methods.

Only if your API doesn't allow you to handle the stream correctly then you should aggregate the ciphertext and perform the decryption on the full ciphertext.