PHP7.4将mcrypt_encrypt升级为openssl_encrypt,加密结果不一致的问题?
以下代码在PHP5.6环境下运行正常:
function priceEncode($enc_key, $price){
$enc_key = base64_decode($enc_key);
// PHP低版本使用,PHP7.1.0起废弃
$size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$pad = $size - (strlen($price) % $size);
$price = $price . str_repeat(chr($pad), $pad);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $enc_key, $iv);
$data = mcrypt_generic($td, $price);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$data = base64_encode($data);
return $data;
}
echo priceEncode('5AE8274196C85364D44938E47D80ACA6', 1222.01); // 得到cPnrXHxzWG6e0GyC7X/kpg==
在PHP7及以上版本,mcrypt
扩展已被废弃,不再作为官方支持。上述示例如何在PHP7以上的版本实现呢?
echo base64_encode(openssl_encrypt($price, 'AES-128-ECB', $enc_key, OPENSSL_RAW_DATA));
使用openssl库,这样实现,输出的结果不一致是什么原因呢?
推荐使用openssl进行操作
function priceEncode($enc_key, $price){
$enc_key = base64_decode($enc_key);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-ECB");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($price, $cipher, $enc_key, $options=OPENSSL_RAW_DATA, $iv);
$data = base64_encode($ciphertext_raw);
return $data;
}
echo priceEncode('5AE8274196C85364D44938E47D80ACA6', 1222.01);
目前是PHP7.4环境下,运行会报错Fatal error: Uncaught Error: Length must be greater than 0 in $iv 那行,AES-128-ECB模式下好像可以不用iv,这样返回的结果却是 jxGY821Kec6RKVxcjVIR1Q==
问题可能出在两个加密函数的实现细节上。mcrypt_encrypt 和 openssl_encrypt 在一些参数和行为上可能有所不同,导致了不同的加密结果。
以下是您提供的 PHP5.6 版本代码的等效 PHP7.4 代码,使用 openssl_encrypt:
php
function priceEncode($enc_key, $price) {
$enc_key = base64_decode($enc_key);
$cipher = 'AES-128-ECB';
// PKCS7 padding
$pad = openssl_cipher_iv_length($cipher);
$price = openssl_encrypt($price, $cipher, $enc_key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
$price = $price . str_repeat(chr($pad - strlen($price) % $pad), $pad);
return base64_encode($price);
}
echo priceEncode('5AE8274196C85364D44938E47D80ACA6', 1222.01);
请注意以下几点:
使用 AES-128-ECB 作为加密算法。
使用 openssl_cipher_iv_length 来获取块大小。
使用 OPENSSL_RAW_DATA 和 OPENSSL_ZERO_PADDING 选项来进行加密和填充。
上述代码实现了在 PHP7.4 中使用 openssl_encrypt 替代 mcrypt_encrypt 的功能。然而,即便采用相同的加密算法和模式,不同的库和版本在具体实现上仍可能存在差异,因此结果可能会有轻微的不同。如果您确实需要与之前的加密结果完全相同,可能需要考虑其他一些因素,如补位方式等。
openssl_cipher_iv_length($cipher)有等于0的情况,作为除数会报错