程序员PHP经验分享

PHP的openssl_encrypt替换mcrypt_encr

2018-06-12  本文已影响25人  lensuntop

由于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两个函数之间的区别。希望通过这些描述能够帮助到和我一样懒的人解决这个头疼的问题。毕竟我忙活了我一天的时间去耐心找到答案。

上一篇下一篇

猜你喜欢

热点阅读