I am working on a Block Storage system, where I have the need to encrypt and authenticate blocks by a client, but also want the server to be able to detect bit corruption while minimizing the work done on the data. The storage blocks are roughly 1MB segments.
One option is to let the client use a AE(AD) cipher (like AES/GCM) and afterwards add a strong checksum. Since AES/GCM is not yet the most optimized cipher (in my Java world), an alternative would be to use a more traditional encrypt-then-HMAC. However, with a normal HMAC, this could not serve as a publicly verifiable checksum. And calculating both, a HMAC and a checksum would double the amount of work which needs to be done (over the message). What about only calculating the checksum over the message, and using a HMAC on this reduced data set?
encrypted = AESCBC(IV, plaintext-1MB) checksum = SHA224(ID | IV | len | encrypted) sig = HMAC(ID | len | checksum) message = ID | IV | len | encrypted | checksum | sig
In this case I calculate a publicly verifiable checksum over the data (so I can detect corruption on the server) and only the client could check in addition to that the HMAC authenticator added. The HMAC does not need to run over all the encrypted data, but uses the checksum as a shortcut. The ID is unique for each segment.
In my case the protocol can't be used as an anonymous oracle and the plaintext length can not be extended boundlessly, however a hash which is more resistant against extension attacks is intentionally used.
I haven't seen much analysis on using ordinary hashes for content authentication. Can anyone can give me a pointer on whether this is safe? (I haven't yet done performance analysis yet; I might simply go with AES/GCM+SHA if that is fast enough). Or is there a more standard construction for generating a publicly verifiable and authenticating tag?