【问题标题】:PHP's mcrypt_encrypt and openssl (AES) output are differentPHP 的 mcrypt_encrypt 和 openssl (AES) 输出不同
【发布时间】:2018-08-18 12:21:33
【问题描述】:

我想从 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";
?>

有什么问题?谢谢

【问题讨论】:

  • 请注意结尾的不同之处? ...这可能会有所帮助:stackoverflow.com/questions/41181905/…
  • @IncredibleHat 这解决了我的问题!非常感谢
  • =) 对不起,我之前很迟钝...
  • @IncredibleHat 没问题.. 谢谢!
  • 最好不要使用PHP mcrypt,它是废弃软件,多年未更新不支持标准PKCS#7(née PKCS#5)填充,只有非标准甚至不能用于二进制数据的空填充。 mcrypt 有许多出色的 bugs 可以追溯到 2003 年。不推荐使用的 mcrypt-extension 将在 PHP 7.2 中删除。而是考虑使用defuseRNCryptor,它们提供了一个完整的解决方案并且正在维护并且是正确的。

标签: php openssl mcrypt


【解决方案1】:

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

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

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

所以 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

【讨论】:

  • 使用 OPENSSL_ZERO_PADDING 时输出为空
  • 我是从openssl_encrypt 那里得到的,也许您使用的是不同的版本。来自 doc cmets:因此,OPENSSL_ZERO_PADDING 禁用了上下文的填充,这意味着您必须手动将自己的填充应用于块大小。不使用 OPENSSL_ZERO_PADDING,您将自动获得 PKCS#7 填充。
  • OPENSSL_ZERO_PADDING 解决了我的 openssl 结果太长但匹配第一个块 +1 的问题
  • 只是一个注释。我不得不模仿 3DES ECB mcrypt,而填充还有一个不同之处。当明文长度适合块大小边界时,实际上根本没有填充,但在 PKCS#7 中,多了一个带有填充的块。因此,对于纯文本 hello wo,mcrypt 填充数据将为 hello wo,但在 PKCS#7 中它将为 hello wo\x08\x08\x08\x08\x08\x08\x08\x08
猜你喜欢
  • 2021-11-07
  • 1970-01-01
  • 2018-09-10
  • 2021-10-27
  • 2013-08-10
  • 2018-11-11
  • 2020-06-12
  • 2020-02-02
  • 1970-01-01
相关资源
最近更新 更多