Is this streamable combination of encryption and MAC secure? I want to combine encryption and MAC.

For encryption I use AES-256 with CBC and PKCS5Padding.
For MAC I use HmacSHA512.

I use the Encrypt-then-Mac approach (calculate MAC over the ciphertext and deliver it with the ciphertext)

The algorithm should be able to process streamed data, and if I calculate the MAC once over the whole ciphertext, there are two possibilities:


Prepend the mac to the ciphertext:

This is a very bad idea, because the encryption part has to encrypt the whole text before it can output the mac. Therefore it's not streamable. On decryption, we have to process the whole ciphertext before knowing if is compromised (also not fully streamable).
Append the mac to the ciphertext:

Better idea, but the decryption part can only check the MAC in the end. Before that, it did output many bytes that could have been changed by an attacker, or it has to wait until it sees the MAC (not streamable again).


So I need a solution which divides the ciphertext into parts and then calculates a MAC for each part. Because the ciphertext shouldn't be much larger than the plaintext, I choose a MAC block size that is greater than the encryption block size (for example 4 kB).

I want to use a pattern like (with $c_X$ = part X of the ciphertext, $m_i$ = part X of the MAC):

$$ m_1 || IV || c_1 || m_2 || c_2 || m_3 || c_3 || \dots $$

The calculation of the first MAC is clear ($k$ being the MAC key):

$$ m_1 = MAC(k, IV || c_1) $$

But then we meet problems. If we just use

$$  m_X = MAC(k, c_X), $$

this wouldn't be secure. An attacker could change the blocks in order, he could duplicate or remove whole blocks, and so on.

So I thought about an idea similar to CBC mode in encryption:

$$ m_X = MAC(k, m_{X-1} || c_X) $$

Is this now secure? And is there a difference to this one?

$$ m_X = MAC(k, c_1 || ... || c_X) $$
It looks like your protocol is secure for integrity purposes, i.e. the receiver will only accept a stream if it is the same as the one sent by the sender (assuming the MAC is not broken).

But if your possible attack scenarios contain a (partial) chosen plaintext attack, the use of CBC makes it weak against the BEAST-like attack against the confidentiality part, mentioned in the comment by CodeInChaos.

For CBC to be secure against chosen-plaintext attacks of the BEAST-style, it is important that each block's "effective initialization vector" (i.e. the previous block or the IV for the first block) is sent not earlier than the content of the block is fixed. If you send your stream in MAC-block pieces (i.e. $m_i || c_i$) and you send one such full piece before the (plaintext of) the first block of the next piece is known, an attacker which can both observe the ciphertext and chose this block of plaintext can use this to verify guesses about other parts of the ciphertext.

In your context of file encryption, quite likely the full file is already fixed when you start encrypting it, thus this attack is not possible. But make sure you document this limitation when creating your program. Alternatively, use other modes like CTR instead of CBC, which are not weak against chosen plaintext attacks.