美文网首页程序员PHP经验分享
PHP的openssl_encrypt替换mcrypt_encr

PHP的openssl_encrypt替换mcrypt_encr

作者: lensuntop | 来源:发表于2018-06-12 12:11 被阅读25次

    由于mcrypt_encrypt的函数在PHP7中已经被废弃,在之前的项目中有一个加密函数需要转换,代码如下:

    $encryptString = 'lensuntop encrypt';

    $key = pack('H*', "bfdecc6724cc96548fb653fa965588c");

    $iv = pack('H*', "404ad092ac31fb6b5bb956ad2943259c");

    $rnd = (int)(microtime(true) * 1000) ^ rand();

    $rnd_text = pack("V", $rnd);

    $packet = $rnd_text . "\0\0\0\0" . "en" . "\0" . $encryptString ;

    $crc32 = crc32($packet);

    $crc32_text = pack("V", $crc32);

    $packet = $rnd_text . $crc32_text . "en" . "\0" . $encryptString ;

    $result = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $packet, MCRYPT_MODE_CFB, $iv);

    现在要保存mcrypt_encrypt函数加密下和新函数openssl_encrypt的加密一致。搜索了一下发现有不少人遇到了我一样的问题。在stackoverflow找到了两个答案

    1、https://stackoverflow.com/questions/41181905/php-mcrypt-encrypt-to-openssl-encrypt-and-openssl-zero-padding-problems

    2、https://stackoverflow.com/questions/45218465/mcrypt-rijndael-128-to-openssl-aes-128-ecb-conversion

    这两个答案都是可以的。作为便捷我直接拷贝一下以上两位的代码:

    代码1:

    $message = "Lorem ipsum";

    $key = "123456789012345678901234";

    $iv = "12345678";

    $message_padded = $message;

    if (strlen($message_padded) % 8) {

        $message_padded = str_pad($message_padded, strlen($message_padded) + 8 - strlen($message_padded) % 8, "\0");

    }

    $encrypted_mcrypt = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv);

    $encrypted_openssl = openssl_encrypt($message_padded, "DES-EDE3-CBC", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv);

    printf("%s => %s\n", bin2hex($message), bin2hex($encrypted_mcrypt));

    printf("%s => %s\n", bin2hex($message_padded), bin2hex($encrypted_openssl));

    代码2:

    class EncryptHelper {

        public static function encrypt128($str) {

            $secret = 'a0a7e7997b6d5fcd55f4b5c32611b87c';

            $block = mcrypt_get_block_size("rijndael_128", "ecb");

            $pad = $block - (strlen($str) % $block); $str .= str_repeat(chr($pad), $pad);

            return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $secret, $str, MCRYPT_MODE_ECB));

        }

         public static function decrypt128($str) {

            $str = base64_decode($str);

            $str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $secret, $str, MCRYPT_MODE_ECB);

            $len = strlen($str); $pad = ord($str[$len - 1]);

            return substr($str, 0, strlen($str) - $pad);

            }

            public static function sslEncrypt128($str) {

                $secret = 'a0a7e7997b6d5fcd55f4b5c32611b87c';

                return base64_encode(openssl_encrypt($str, 'aes-256-ecb', $secret, OPENSSL_RAW_DATA));

            }

    }

    printf("%s\n", EncryptHelper::encrypt128('lensuntop encrypt'));

    printf("%s\n", EncryptHelper::sslEncrypt128('lensuntop encrypt'));

    可惜的是我的项目中加密并不是和这两位的一样。但是既然他们能替换成一样的,自然在我的项目中也能找到解决方案。通过观察是函数中使用的加密算法不一样。通过PHP的官网 http://php.net/manual/en/function.openssl-get-cipher-methods.php 找到了所有的加密算法。如下图:

    来源PHP官网

    由于我的函数中使用到的是 MCRYPT_RIJNDAEL_128 和 MCRYPT_MODE_CFB 在代码2中MCRYPT_RIJNDAEL_128 对应的是aes,而且代码2中将加密字符进行了转换,所有在openssl_encrypt使用 aes-256-ecb 却可以将其加密。那么对于我项目中用到了 MCRYPT_RIJNDAEL_128 和 MCRYPT_MODE_CFB 。那么对应的应该是 AES-128-CFB、AES-128-CFB1、AES-128-CFB8或者是AES-256-CFB、AES-256-CFB1、AES-256-CFB8。在输入AES-128-CFB8后发现两个函数加密出来的字符串是一样的。到此问题解决!

    由于时间的关系,我并没有深入去了解每个算法的不一样,也没有去看源代码进行对比mcrypt_encrypt和openssl_encrypt两个函数之间的区别。希望通过这些描述能够帮助到和我一样懒的人解决这个头疼的问题。毕竟我忙活了我一天的时间去耐心找到答案。

    相关文章

      网友评论

        本文标题:PHP的openssl_encrypt替换mcrypt_encr

        本文链接:https://www.haomeiwen.com/subject/jjsleftx.html