1
$\begingroup$

I saw a little close to these questions but not exactly.

Encryption method AES-256-Rijndael-CBC:

if we have multiple cipher chunks that look like this: {iv}{cipheredchunk}{chiphered chunk}{chiphered chunk}....

I earlier got noted that we should never use the same IV for other chunks since chunks could be identical, so we need something like this:

{IV+cipheredchunk}{IV+chiphered chunk}{IV+chiphered chunk}...

My question is, is it okay to avoid adding a bunch of 16 bytes long random IV for every chunk, maybe we could use one fully random IV for the first chunk, and for next chunk use the first 16bytes of that chunk as iv for next block?

Do we keep the safety of the encryption?

Edit:

Every "Ciphered Chunk" is a completly finished encrypted message in AES256 CBC. So if we for example have the whole plaintext message to encrypt of "abcdefghijk" and we say that every chunk is 3 letters/bytes then we do:

AES256CBC encryption on "abc" -> ciphered text("Ciphered chunk")
AES256CBC encryption on "def" -> ciphered text("Ciphered chunk")
AES256CBC encryption on "ghi" -> ciphered text("Ciphered chunk")
AES256CBC encryption on "jk" -> ciphered text("Ciphered chunk")

The reason i am doing this instead of ciphering the whole plaintext at once is since i am dealing with incredibly large files of many GB which no program or computer can handle at once.

So im trying to cipher small parts of the file in AES256 CBC mode and basically append them next to each other :)

$\endgroup$
3
$\begingroup$

You can indeed avoid having an explicit IV for each chunk in favor of an implicit one, and using the previous encryption's last ciphertext block is indeed one way. But:

  • You almost certainly need authenticated encryption that provides not just confidentiality but also message authenticity. Read up on the EFail attack, one of whose causes is CBC-based encryption software that doesn't protect ciphertexts from tampering (or more precisely, does so in an inadequate fashion).
  • Once you add the message authenticity requirement, it becomes very hard to escape ciphertext expansion (ciphertexts longer than the plaintext) because the ordinary way to achieve it requires you to include a message authenticity tag for each chunk. You can tune the overhead by upping the size of each encrypted chunk, but that of course increases how much memory you need to encrypt/decrypt one.

Be aware that what you're trying to do carries countless pitfalls and that it's much less risky if you use a library written by cryptography experts or, at the very very least, copy one of their designs (and copy it successfully). For example, recent versions of the popular Libsodium library include an encrypted streams and file encryption module that's designed to safely perform precisely this sort of constant memory chunked authenticated encryption, but do it carefully:

This high-level API encrypts a sequence of messages, or a single message split into an arbitrary number of chunks, using a secret key, with the following properties:

  • Messages cannot be truncated, removed, reordered, duplicated or modified without this being detected by the decryption functions.
  • The same sequence encrypted twice will produce different ciphertexts.
  • An authentication tag is added to each encrypted message: stream corruption will be detected early, without having to read the stream until the end.
  • Each message can include additional data (ex: timestamp, protocol version) in the computation of the authentication tag.
  • Messages can have different sizes.
  • There are no practical limits to the total length of the stream, or to the total number of individual messages.
  • Ratcheting: at any point in the stream, it is possible to "forget" the key used to encrypt the previous messages, and switch to a new key.

This API can be used to securely send an ordered sequence of messages to a peer. Since the length of the stream is not limited, it can also be used to encrypt files regardless of their size.

It transparently generates nonces and automatically handles key rotation.

Your CBC-based approach won't achieve all of this.


That said, just for theory's sake, an alternative way of avoiding ciphertext expansion in CBC is to use a second key and ECB encryption to generate implicit IVs from a counter or nonce. First you generate and share or derive two block cipher keys $k_1$ (for IV generation) and $k_2$ (for encryption), and a public nonce $\mathrm{IV}$. Then for each numbered chunk $m_1, \dots, m_n$, you encrypt each block this way:

$$ \begin{align} \mathrm{IV}_1 & = \mathrm{AES}_{k_1}(\mathrm{IV} \oplus 1) \\ c_1 & = \mathrm{AES\text-CBC}_{k_2}^{\mathrm{IV}_1}(m_1) \\ & \vdots \\ \mathrm{IV}_i & = \mathrm{AES}_{k_1}(\mathrm{IV} \oplus i) \\ c_i & = \mathrm{AES\text-CBC}_{k_2}^{\mathrm{IV}_i}(m_i) \\ & \vdots \\ \mathrm{IV}_n & = \mathrm{AES}_{k_1}(\mathrm{IV} \oplus n) \\ c_n & = \mathrm{AES\text-CBC}_{k_2}^{\mathrm{IV}_n}(m_n) \end{align} $$

Since the recipient knows $k_1$, $k_2$ and $\mathrm{IV}$, and can also count, they can reconstruct the $\mathrm{IV}_i$ values without the sender having to transmit them.

| improve this answer | |
$\endgroup$
  • $\begingroup$ "First you generate and share two block cipher keys" Better to generate/share one key then derive k1, k2, and a MAC key. $\endgroup$ – Future Security Dec 27 '19 at 17:14
  • $\begingroup$ @FutureSecurity: I"ve edited it to "generate and share or derive." $\endgroup$ – Luis Casillas Dec 27 '19 at 17:22
1
$\begingroup$
  • First of all AES!=Rijndael. I'm assuming that 256 is the key size.

  • Yes, the IV in CBC mode must not be reused, actually, it is more than that, the IV must be unpredictable.

  • Let remember how the encryption in CBC mode is performed;

    \begin{align} C_1 &= Enc_k(P_1 \oplus IV)\\ C_i &= Enc_k(P_i \oplus C_{i-1}),\;\; 1 < i \leq nb, \end{align} where $nb$ is the number of blocks. The IV is for the first block, and the rest encryption is using the previous ciphertext for the IV, chaining. Therefore, each ciphertext depends on the output of the previous ciphertext expect the first one where we use IV. We can see this chaining also from the equation;

$$C_j = Enc_k(P_j \oplus Enc_k(P_{j-1} \oplus \cdots Enc_k(P_1 \oplus IV)\cdots)).$$

  • AES CBC in need of multiple IV's, possible to avoid creating duplicate IV's by using resulting ciphertext 16 bytes as next iv?

CBC needs a new unpredictable IV for new encryption which can be multiple blocks and can require padding.

  • My question is, is it okay to avoid adding a bunch of 16 bytes long random IV for every chunk, maybe we could use one fully random IV for first chunk, and for next chunk use the first 16bytes of that chunk as iv for next block?

If you look carefully, actually this is what CBC mode does.

  • Break into parts and continue (for updated question)

Just use the last ciphertext block as the IV of the next part. There is nothing wrong dividing the encryption and continue.


  • And, a piece of usual advice;

CBC mode is archaic and can only provide confidentiality. In today's standards, we use authenticated encryption modes like AES-GCM and Chacha20-Poly1305 which can provide Confidentiality, Integrity, and authentication altogether.


You can also break files into part with the AES-GCM or other modes like;

Assume that you divide the file into $n$ parts. Encrypt each of them with AES-GCM with the following additions. Prefix each part before encryption as follows;

$tag_0 = ""$

$\text{for } i \text{ from } 1 \text{ to } n$

$\quad(ciphertextBlock_i, tag_i) = \text{AES-GCM}( i:n \mathbin\| tag_i-1 \mathbin\| plaintextBlock_i)$

  • prefix each part with the part number as $i:n$
  • prefix each part except the first one with the authentication tag of the previous part.

With these, you have now a chain that can be controlled after decryption. You can detect, additions, deletions. The order is under your control, you can send even without the order. However, you need to check the prefix.

You can also

  • add the part size, and
  • add the time of encryption, too if you fear the replay attack.
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks for being informative, i believe i asked the question really bad with details, sorry for that!, i will edit the question. $\endgroup$ – CoffeDev Dec 26 '19 at 16:21
  • 1
    $\begingroup$ Just use the last ciphertext block as the IV of the next part. There is nothing wrong dividing the encryption and continue. $\endgroup$ – kelalaka Dec 26 '19 at 16:30
  • $\begingroup$ With CBC mode the IV can be reused, it just has to be unpredictable. $\endgroup$ – Swashbuckler Dec 27 '19 at 21:20
  • $\begingroup$ @Swashbuckler Reusing keys with AES-CBC $\endgroup$ – kelalaka Dec 27 '19 at 21:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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