# Authenticated encryption and file data integrity

I've got a task to provide the integrity and an authenticated encryption for files in our application. I need an assurance if my way of thinking is correct.

I can't use AES GCM, I have to stay with CBC mode.

File is logicly divided in 5MiB chunks that are going to be encrypted using same key. IV of first block is randomly generated and the IVs of next blocks are going to be extracted from previous block ciphertext.

Here, below I choosed two possible scenarios how to provide an authenticated encryption and data integrity for file:

First option

At first I encrypt first chunk of file with key and recive ciphertext.

Next I calculate hmac(key, ciphertext) and store it to verify during decryption. For each next encrypted chunk of file I create mac with below formula:

hmac(key, previous_hmac || ciphertext)


And store it to verify during decryption.

Is it proper to do it this way? Is it appropriate to store only last computed hmac in this chained hmac version alongside encrypted file, if it's not important which block was violated, for veryfication purposes?

Second option

The second solution I consider, is to calculate:

hmac(key, block_number || ciphertext)


for each chunk of file and store computed MAC alongside each ciphertext for veryfication during decryption attempt.

ciphertext is encrypted file fragment and block_number is constant bit width integer, which value is fragment offset in file.

Is this an acceptable solution? I know it allows to find violated block among unimpaired ones.

I'm not quite sure, which one of given above solutions is better. I would be thankful if someone could give me an advice which one should I chose or propose a better solution. Any links to lectures also would be appreciated. Thanks.

the IVs of next blocks are going to be extracted from previous block ciphertext.

Here assuming chunks since CBC requires IV only once per message/chunk.

IV of CBC should be unpredictable, i.e random. It is not a good idea to extract from a known source. Use randomly generated per chunk.

First option

Enables chaining, you should also add the IV with the ciphertext. You can store the last HMAC since you can generate from the beginning. As you said this prevents the detection of chunks that have errors during transmission. This can cause re-transmit all the chunks.

Second option

There is an attack on this case. If the same key is used for different messages, and an attacker may replace one chunk with a chunk from an old message and you cannot notice this attack if there is no validation for the message.

Better solution

Use chaining and send the intermediate HMAC results, too. This is actually combing of first and second. It enables to detection of the errored chunks and prevents the replacing attack on the second option.