Table of Contents

PHP RFC: Deprecate (then Remove) Mcrypt

Introduction

Let's get rid of ext/mcrypt, which is abandonware and inhibits the growth of the language, as soon as humanly possible.

Proposal

In PHP 7.1, all mcrypt_* functions will raise an E_DEPRECATED notice.

In PHP 7.1+1 (be it 7.2 or 8.0), the mcrypt extension will be moved out of core and into PECL, where people who *really* want to install it may still do so if they can install PHP extensions from PECL.

This RFC does not concern itself with the concept of shims or compatibility layers, and those topics are out of scope. If this RFC passes, another RFC could be drafted by interested parties to propose such a feature at a later date.

Background Information (Regarding Security)

A survey of websites where people share cryptography code reveals a lot about how people use mcrypt. You'll most likely find gems like this:

/**
 * Don't use this. It was copied from StackOverflow to demonstrate how
 * unsuccessful developers are at using the mcrypt extension:
 */
function fnEncrypt($sValue, $sSecretKey)
{
    return rtrim(
        base64_encode(
            mcrypt_encrypt(
                MCRYPT_RIJNDAEL_256,
                $sSecretKey, $sValue,
                MCRYPT_MODE_ECB,
                mcrypt_create_iv(
                    mcrypt_get_iv_size(
                        MCRYPT_RIJNDAEL_256,
                        MCRYPT_MODE_ECB
                    ),
                    MCRYPT_RAND)
                )
            ), "\0"
        );
}

function fnDecrypt($sValue, $sSecretKey)
{
    return rtrim(
        mcrypt_decrypt(
            MCRYPT_RIJNDAEL_256,
            $sSecretKey,
            base64_decode($sValue),
            MCRYPT_MODE_ECB,
            mcrypt_create_iv(
                mcrypt_get_iv_size(
                    MCRYPT_RIJNDAEL_256,
                    MCRYPT_MODE_ECB
                ),
                MCRYPT_RAND
            )
        ), "\0"
    );
}

Problems with this code:

Mcrypt has a lot of design warts and puts a lot of burden on the implementer to choose the right components (and stitch them together correctly). Blaming the implementer leads to error-prone cryptographic designs. Error-prone cryptographic designs leads to insecure applications.

If libmcrypt were still being maintained, we could work with the libmcrypt team to improve it. Unfortunately, it was abandoned in 2007, and contains unfixed bugs and patches that will never be merged.

Everything libmcrypt can do, openssl can do too (and often better), either out-of-the-box or via its support for pluggable ciphers.

For example: OpenSSL's AES implementation (which mcrypt still called MCRYPT_RIJNDAEL_128 before it was abandoned) uses AES-NI on modern processors to deliver very fast AES that withstands cache-timing attacks. Mcrypt's AES still used S-boxes.

Comparing libmcrypt to openssl, you will find that it is:

Backward Incompatible Changes

Any cryptography code that depends on mcrypt will need to be refactored against openssl. This isn't as difficult as it sounds, provided you're using a trustworthy cipher (e.g. MCRYPT_RIJNDAEL_128). Based on this 3v4l, I can generally conclude that the following MCRYPT ciphers are not currently supported by openssl:

This is an acceptable loss: Most of the ciphers in the list above should not be used in new software anyway. Most cryptography experts would consider their inclusion in any software written in 2016 to be a code smell and indicative of a bad protocol design. Some of them (e.g. Enigma) are outright insecure and should not be used at all.

Proposed PHP Version(s)

Deprecation: Next minor version (7.1.0).

Removal from core: The following major/minor version (7.2.0 or 8.0.0).

Proposed Voting Choices

Vote “Yes” to raise an E_DEPRECATED notice in PHP 7.1 when any mcrypt function is used and to remove the extension from core in 7.1+1.

Vote “No” otherwise.

Since this would break backwards compatibility, a 2/3 majority is required.

Deprecate then Remove Mcrypt from the PHP Core?
Real name Yes No
bwoebi (bwoebi)  
colinodell (colinodell)  
davey (davey)  
derick (derick)  
diegopires (diegopires)  
dmitry (dmitry)  
frozenfire (frozenfire)  
gasolwu (gasolwu)  
jedisct1 (jedisct1)  
krakjoe (krakjoe)  
leigh (leigh)  
lstrojny (lstrojny)  
mariano (mariano)  
mbeccati (mbeccati)  
mcmic (mcmic)  
mightyuhu (mightyuhu)  
mikemike (mikemike)  
nikic (nikic)  
ocramius (ocramius)  
pauloelr (pauloelr)  
philstu (philstu)  
pollita (pollita)  
ramsey (ramsey)  
remi (remi)  
sammyk (sammyk)  
svpernova09 (svpernova09)  
trowski (trowski)  
willfitch (willfitch)  
zimt (zimt)  
Final result: 23 6
This poll has been closed.

This vote is opened on March 15th, 2016 and will close March 22nd at 17:00 UTC as announced on list.

Patches and Tests

Patches are available:

References

Rejected Features