What is best to use (for message integrity) between…

  1. AES(Data) + HMAC(Data)
  2. AES(Data + HMAC(Data))
  3. AES(Data + Hash(Data))

…and why?

  • 3
    $\begingroup$ @user2908183 Good discussion here... $\endgroup$
    – hunter
    Commented Nov 1, 2013 at 21:58
  • $\begingroup$ @RickyDemer - on second thought - I see your point - I'm removing my initial comments. $\endgroup$
    – hunter
    Commented Nov 1, 2013 at 22:08

2 Answers 2


"Encrypted hash" totally fails if the encryption uses a malleable mode like CTR. CTR runs AES in a stream-cipher-like mode where the data to encrypt is simply XORed with a key-dependent stream, so the attacker can flip bits with extreme precision; so if the attacker guesses the contents, he can modify them and fix the hash easily.

More generally, if you want a MAC then use a MAC. The "encrypted hash" is just a homemade attempt at a MAC algorithm, and we know that homemade algorithms are rarely strong, and even when they are we cannot make sure that they really are strong.

As for how to combine encryption and a MAC, this is a well-known questions for which a lot of theory and practice has been accumulated; see this question. To sum it up: you want to compute the MAC over the encrypted data, because it avoids any issue with the MAC algorithm leaking information on the processed data, and it protects the decryption implementation from malformed data.

Now, HMAC seems to be reasonably well-behaved and not to leak information about the data on which it is applied. Your setups 1 and 2 are what is used by, respectively, SSH and SSL/TLS. In neither case did it prove fatal; however, the lack of protection on the encrypted format allowed various padding oracle attacks to experience some success on implementations which were not sufficiently careful when decrypting malformed input data.

  • $\begingroup$ OK... How much long should the hmac key be for SAH1 and SHA256 respectly? Using a key for received messages (client_read_hmac_key) and another key for sent messages (client_write_hmac_key) should allow me to use the same AES key for both sending and receiving because using two different keys for HMAC mitigates the replay attack of a client command to the server. Am I right? $\endgroup$ Commented Nov 2, 2013 at 15:00
  • $\begingroup$ PS: AES will work in CBC mode... $\endgroup$ Commented Nov 2, 2013 at 15:08
  • $\begingroup$ A key for HMAC should be large enough to prevent brute force, and needs not be longer than that. So, 128 bits. On a general basis, you all keys should be distinct, so you would need four keys (one for HMAC and one for encryption, in each direction). Knowing whether some keys can be shared is tricky. The usual setup is that, from a master key, a "key block" is derived with a Key Derivation Function, which is split into all needed keys. See SSL/TLS for an example. $\endgroup$ Commented Nov 2, 2013 at 16:19
  • $\begingroup$ Also, I must add that you seem to be in the process of designing your own protocol, with the help of a Q&A Web site where random strangers give their opinion. This path usually leads to sorrow. You really should try to use existing protocols and implementations where hard details have been ironed out (i.e. SSL, OpenPGP...). $\endgroup$ Commented Nov 2, 2013 at 16:24
  • $\begingroup$ I definitely have to develop my own protocol because of some particular needs... So what is best to use? AES(Data) + HMAC(AES(Data)) or AES(Data + HMAC(AES(Data))) ? Thanks $\endgroup$ Commented Nov 10, 2013 at 16:58

2, because the only issue is that there might be a feasible way to have a non-negligible
probability of producing a new AES ciphertext that decrypts to already-encrypted data.

(Of course, as pointed to by hunter, AES(data) + HMAC(AES(data)) is even better.)


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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