I am working with this PHP encryption class using MCRYPT_RIJNDAEL_256 and MCRYPT_MODE_CBC with a fixed 32-byte (64 character) HMAC key, as my basis.

The class is a result of previous discussions and remarks made on this blog page. and seems like a solid implementation as such. However there are a few aspects discussed I am still not clear on:

The only thing it adds is predictable plaintext positions which will aide a cryptanalyst. I recommend removing the serialization and using PKCS7 padding.

comment 1304.

Now that the encryption method uses HMAC and that the serialization avoids the '\0' padding issue. Is it still a good idea to use a PKCS padding even when the HMAC is used (and the serialization kept)?

Or in other words, does the HMAC alone solve the "predictable plaintext position"?

My assumptions about the goods for serialization, is that it would seem to make the text length less predictable, even is the message is one plain text string, say for short predictable length, especially for a fixed size number. Though, I just want to make sure that the serialization is not a counter negative.

  • PS I've asked the user to post here as it mainly is about padding modes and MAC. Hope that's OK. Jan 29, 2015 at 22:31

2 Answers 2


According to the PHP documentation, Serialize()'ed output can contain null bytes, and needs to be handled accordingly. So, unless there is a guarantee (which I don't see) that a null byte cannot be at the end of the serialized data, then yes, it is most definitely advisable to use PKCS#7 padding.

In the case of the author of that bit of code, he is in fact assured that the data will not end in a null byte, because he is appending the MAC to the plaintext before encryption, in a MAC-then-encrypt scheme. This is wrong. Do not do this. This is what leads to padding oracle attacks like POODLE. You need to ensure the integrity of the ciphertext before decrypting, which means encrypt-then-MAC instead.

Additionally, the HMAC key appears to be strongly related to the encryption key. This is not ideal. The HMAC key and encryption key should not be related.

Third, the HMAC calculation needs to be done in constant time to prevent timing attacks. Techniques for doing this in PHP are covered in a comment on hash_hmac.

  • +1 to do a rather complete security review of the code Jan 29, 2015 at 22:50
  • Out of ignorance though. In an encrypt-then-MAC context, is a constant hmac key more desirable than an hmac slightly (but not directly) related to the key, for purpose of the hmac key being different every time? Obviously not strongly related like that class, but say a minor partial mix with a plain key which are then both hashed to a key used to generate the hmac.
    – hexalys
    Jan 30, 2015 at 8:00
  • 1
    @hexalys If you only have one secret value then you can apply a KBKDF such as HKDF two times (using a specific ID for each of the key). As a HMAC does not directly use AES using the same key data within HMAC is relatively save. Unfortunately KDF's are not often present in libraries; you can however concatenate the secret & ID and then perform a hash over the result to create a poor mans KDF which is still relatively safe. Jan 30, 2015 at 10:36

There are separate requirements for performing deterministic padding mode and providing an authentication tag.

The padding is required for ECB and CBC modes of operation. These modes only handle messages that are N times the block size in length. The standard PHP padding is not deterministic if the message may end with zero valued bytes.

The authentication tag (provided by a HMAC, for instance) is required to protect the integrity of the message and to show that it was send by the expected sender (authenticity). If integrity of the ciphertext is not validated then any attacker may send or alter messages (active attacks or man-in-the-middle attacks). This may even break confidentiality if padding oracle attacks are possible.

So you should try and use PKCS#7 compatible padding even if you provide a HMAC and especially if your messages may end with zero. The comment about "predictable plaintext positions" may be ignored; you should expect attackers to know a certain amount of information about the plaintext (such as the size of the plaintext). This is OK as long as the integrity and confidentiality has been safe-guarded.

Note that the author of the article seems to acquire quite a bit of education from the comments. The fact that the author confuses Rijndael with a block size of 256 bits (MCRYPT_RIJNDAEL_256 in PHP) with AES shows that the author doesn't know much about cryptography at all.

You should not trust this code. You need to understand cryptography before using a library or code snippet. At least try and use a well known container format if you're unsure. Anybody can apply AES. At least 90% of StackOverflow (where this question was posted before) however applies it incorrectly.

  • Thanks. That clarifies PKCS7 for me. I know there is a shipload of poor code out there. I was even surprised that CodeIgniter contained some. I try to always do my homework. Though the case is interesting because of the education process it contained. It helps me understand cryptography more, in depth, along with the very helpful added full review from @Xander.
    – hexalys
    Jan 29, 2015 at 23:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .