The situation is that I download a mp3 file (song) and I encrypt blocks of data (4096 bites for example). The output of every encryption operation I save it in a new file.

When I play the song (encrypted file) I work with buffers. If I seek near the end of the song, for example, I need to somehow extract the IV that I used for encryption.

How can I generate a safe IV for encryption and be able to decrypt in this situation ?

  • $\begingroup$ Your question title and question body don't seem to relate to each other. The IV only matters for decryption in CBC in the first block, the XOR operation on all blocks past the first, use the previous block's cipherText, not the IV. $\endgroup$ – Kritner Sep 25 '17 at 12:15
  • $\begingroup$ @Kritner Evidently, ”block“ in the question doesn't mean a block as in a block cipher block, but a block as in a fixed-size piece of storage. $\endgroup$ – Gilles 'SO- stop being evil' Sep 25 '17 at 20:08

The question tells CBC is used. I assume that, even though the suggestions to use CTR are good. I consider a block cipher with block size of $b$ octets (e.g. $b=8$ for DES/3DES, $b=16$ for AES), and that the IV used at encryption (possibly random) is stored in the first $b$ octets of the encrypted file, with the ciphertext following.

With CBC, decryption can start at any position in the file. To decipher from octet at offset $n\ge b$ in the enciphered file (offset $n-b$ in the original file), start reading at offset $b(\lfloor n/b\rfloor-1)$, read $b$ octets from there and use that as IV, start deciphering normally but discard the first $n\bmod b$ octets. When $b$ is a power of two (which is most common), in C or similar languages, start reading the IV at offset ((b-1)|n)-(2*b-1) and skip (b-1)&n octets.

In the case of streaming audio or video, this simplifies to: make $n$ a multiple of $b$ (typically, a multiple of 4096 will do), use the first $b$ octets as IV, and play what's deciphered with a player that mutes until it found a sync pattern.


Do you have to use CBC? For random read access, Cipher Feedback or Counter mode are usually preferred. For either you'd still need a random number, an IV for CFB and a shorter nonce for CTR (to leave space for the actual counter bits). You'd have to store them with the encrypted data, of course, and what people usually do is to put the IV into the first block of the encrypted data. For reading the nth block of the actual song, you'd have to then

  1. CFB: read the nth block of the encrypted data, encrypt it with the AES key and xor it with the next block of encrypted data.
  2. CTR: read the first block of the encrypted data, add n to it (or n-1 if your encryption starts at n=0) encrypt that with the AES key, and xor that with the n+1th block of encrypted data.

In both cases you can access any block quickly and save space since you need only one random number. Make sure it's really random, though, and never reused.

  • $\begingroup$ I recommend using a purely random initial counter value for CTR. Separating a message nonce and a block-in-message counter tends to lead to mistakes such as a too short nonce that has a non-negligible probability of repeating, a too-short counter that repeats for long messages, or a bug in the ICV formatting that leads to nonce repetition. $\endgroup$ – Gilles 'SO- stop being evil' Sep 25 '17 at 20:06
  • $\begingroup$ For any mode, especially for CTR where the attack can be devastating, it's important to note that if you re-encrypt a file, you must pick a new IV. $\endgroup$ – Gilles 'SO- stop being evil' Sep 25 '17 at 20:08
  • 1
    $\begingroup$ CFB and CBC work exactly as well for random read access. $\endgroup$ – fgrieu Sep 26 '17 at 17:09

I'll just add a bit of a different perspective, though @wallenborn already gave an excellent answer.

The encryption schemes you mentioned are typically used due to a simple yet fundamental problem: what if you encrypt the same message block twice, using the same key?

In block cyphers, this process always gives you the same output, so your attacker could gain some knowledge on the contents of your message by analysing the patterns of the blocks.

There are a few encryption schemes mentioned here, but the goal is to always mix your message block type with some unpredictability in order to make sure no two equal message blocks encrypt the same way. You could indeed just add a random IV in each block as one of the answer suggests, but as we know, there's always a - hopefully small - chance you get two equal numbers when you ask for IVs. Those two blocks will be encrypted the same way for sure, and if you are unlucky and they have the same message, they will be exactly equal.

As such, I'd use counter mode instead, which, by changing the random IV with the count of every block, ensures that you get different encryptions in every block, even if your message has repetitions.

  • $\begingroup$ A random IV is perfectly fine, and is the right way to do it. Note that some modes (such as CBC) require an IV that's unpredictable, not just unique. If your random IVs are repeated then you did something wrong, either using bad parameters (e.g. the IV is too small) or a bad RNG. Either way, if you can't trust your IV generation, what makes you think you can trust your key generation? $\endgroup$ – Gilles 'SO- stop being evil' Sep 26 '17 at 22:29

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.