in Web Development

Backwards Compatibility with PHP 7 and Mcrypt Key Sizes

We recently upgraded a server to PHP7 which interacts via a client API with an older server running PHP 5.5. One of the authentication mechanisms utilizes the functions mcrypt_encrypt. An interesting problem arose in the client library, as the mcrypt module was deprecated in PHP 5.6 with breaking changes:

Invalid key and iv sizes are no longer accepted. mcrypt_encrypt() will now throw a warning and return FALSE if the inputs are invalid. Previously keys and IVs were padded with ‘\0‘ bytes to the next valid size

The old PHP 5.5 server was using an encryption key which had an unsupported number of characters. The AES encryption specification only permits the usage of exactly 16, 24, or 32 characters. On the PHP 7 server, this quickly led to the following PHP error:

mcrypt_encrypt(): Key of size 18 not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported

As a workaround, we quickly created a series of backwards compatible helper functions. These mcrypt helper functions match the handling of PHP 5.5. In essence, they pad improperly sized keys with null bytes until they match a valid size according to the AES specification.

Below you will find a helper function for generating valid AES encryption keys with null byte padding followed by example usage with an invalid key length. We recognize that null byte padding is not optimal (use PKCS7 instead), and are merely demonstrating a backwards compatible helper:

One thing you’ll quickly notice is that when you decrypt a value using mcrypt_decrypt, the null bytes still persist in the decrypted string. You need to accomodate for this in your code by removing the null bytes which were appended to the string, as demonstrated in the code.

Now that we’ve hopefully helped you with your mcrypt compatibility issues, let me leave you with a parting note. The mcrypt module has been deprecated as of PHP 7.1 and it’s highly encouraged that you switch to using password_hash() and password_verify(). One of the primary reasons for moving away from mcrypt is it’s difficult to securely implement mcrypt functions on your own without leaving possible security holes. To learn more on why you should avoid using mcrypt, read this article entitled If You’re Typing the Word MCRYPT Into Your PHP Code, You’re Doing It Wrong.


Write a Comment