PHP 的 mcrypt_encrypt 和 openssl (AES) 输出不同

PHP's mcrypt_encrypt and openssl (AES) output are different

我想从 mcrypt_encrypt() 移动到 openssl_encrypt() 以进行 AES 256 加密

但是加密后的数据不一样!

例如mcrypt_encrypt()输出:

Od2i8FHmWvMeXt+HwCy7k93koPVClK1erHsZwoB6sUE=

和openssl_encrypt()输出:

Od2i8FHmWvMeXt+HwCy7kyCt0nvHTaO4IdjdiF15LAc= 

我的代码:

<?php
$encryption_key = openssl_random_pseudo_bytes(32);
$iv = openssl_random_pseudo_bytes(16);
$data = "Here's some data to encrypt!";
$encrypted = openssl_encrypt($data, "aes-256-cbc", $encryption_key, 0, $iv);
echo "encrypted: $encrypted\n\n";
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $encryption_key, $data, MCRYPT_MODE_CBC, $iv));
echo "encrypted: $encrypted\n\n";
?>

问题是什么?谢谢

很有可能是填充。请注意,每个块的第一个块相同,最后一个块不同。

被加密的文本是 28 个字节,所以最后一个块将有 4 个字节的填充:16-(28%16) = 4。

PHP mcrypt 不支持标准 PKCS#7(née PKCS#5)填充,仅 non-standard 空填充。

因此PHP mcrypt 将指定 4 字节的 0x00 和 openssl 的 4 字节的 0x04。参见 PKCS#7 padding

因此,如果您想使用 openssl_encrypt 创建相同的加密输出,您还需要指定零填充选项 (OPENSSL_ZERO_PADDING) 添加空填充你自己。注意:空填充不可靠,因为它不能正确处理所有二进制数据。

示例:openssl_encrypt($data, "aes-256-cbc", $encryption_key, OPENSSL_ZERO_PADDING, $iv);


mcrypt_encrypt():
Base64:Od2i8FHmWvMeXt+HwCy7k93koPVClK1erHsZwoB6sUE=
十六进制:39DDA2F051E65AF31E5EDF87C02CBB93 DDE4A0F54294AD5EAC7B19C2807AB141

openssl_encrypt:
Base64:Od2i8FHmWvMeXt+HwCy7kyCt0nvHTaO4IdjdiF15LAc=
十六进制:39DDA2F051E65AF31E5EDF87C02CBB93 20ADD27BC74DA3B821D8DD885D792C07