当前位置: 首页 > 知识库问答 >
问题:

php - PHP7.1废弃加密方法替换方案: mcrypt_encrypt VS openssl_encrypt 遇到的问题?

秦鸿羽
2023-11-10
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库,这样实现,输出的结果不一致是什么原因呢?

共有3个答案

薄伟彦
2023-11-10

aes加密的结果本来就是相同字符每次得到的密文不同的啊。

两个方法加密的结果互相不能解密才是问题。

openssl_encrypt 第五个参数是iv

image.png

姜森
2023-11-10

https://www.php.net/manual/zh/function.mcrypt-encrypt.php

If you're writing code to encrypt/encrypt data in 2015, you should use openssl_encrypt() and openssl_decrypt(). The underlying library (libmcrypt) has been abandoned since 2007, and performs far worse than OpenSSL (which leverages AES-NI on modern processors and is cache-timing safe).

Also, MCRYPT_RIJNDAEL_256 is not AES-256, it's a different variant of the Rijndael block cipher. If you want AES-256 in mcrypt, you have to use MCRYPT_RIJNDAEL_128 with a 32-byte key. OpenSSL makes it more obvious which mode you are using (i.e. 'aes-128-cbc' vs 'aes-256-ctr').

OpenSSL also uses PKCS7 padding with CBC mode rather than mcrypt's NULL byte padding. Thus, mcrypt is more likely to make your code vulnerable to padding oracle attacks than OpenSSL.

https://paragonie.com/blog/2015/05/if-you-re-typing-word-mcrypt-into-your-code-you-re-doing-it-wrong

Surprise! MCRYPT_RIJNDAEL_256 doesn't mean AES-256.

All variants of AES use a 128-bit block size with varying key lengths (128, 192, or 256). This means that MCRYPT_RIJNDAEL_128 is the only correct choice if you want AES.

MCRYPT_RIJNDAEL_192 and MCRYPT_RIJNDAEL_256 instead refer to non-standard, less-studied variants of the Rijndael block cipher that operate on larger blocks.

Considering that AES-256 has much worse key scheduling than AES-128, it's not at all unreasonable to suspect there might be unknown weaknesses in the non-standard Rijndael variants that are not present in the standardized 128-bit block size version of the algorithm. At the very least, it makes interoperability with other encryption libraries that only implement AES a challenge.

殳越
2023-11-10

前人挖坑,后人遭殃。

1、源代码里面用的 MCRYPT_RIJNDAEL_128 让人第一感觉,是 AES-128,而提供的 key 的长度是32 字符,经过 base64_decode 后,为 24 字符,也就是实际对应的应该是 AES-192

2、原文里面还添加了个 IV 的处理,而 ECB 是不支持 IV 的。

看起来是 mcrypt 会根据密钥长度自行选定加密长度算法,也就是自动选择了 AES-192-ECB,而 OpenSSL 则始终遵守了传第加密算法,将原本 24 字符长度的 key ,截断成了 AES-128 所需要的 16 位,所以不一致,如果你把传递给 mcrypt 的密钥长度裁剪成 16 位,你就会发现他们的加密结果也一样了。

而这里肯定是为了兼容之前的代码,所以这里要改的就是把 AES-128-ECB 改为 AES-192-ECB 就好了。

<?phpfunction priceEncode($key, $text){    $key = base64_decode($key);    $size = 16;    $pad = $size - (strlen($text) % $size);    $text .= str_repeat(chr($pad), $pad);    $cipher = 'aes-192-ecb';    $context = openssl_encrypt($text, $cipher, $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING);    return base64_encode($context);}$key = '5AE8274196C85364D44938E47D80ACA6';$text = '1222.01';var_dump(priceEncode($key, $text) === 'cPnrXHxzWG6e0GyC7X/kpg==');

注:前文中位、字符 均表示使用 strlen 获得的结果。

 类似资料:
  • 本文向大家介绍PHP 7.1中AES加解密方法mcrypt_module_open()的替换方案,包括了PHP 7.1中AES加解密方法mcrypt_module_open()的替换方案的使用技巧和注意事项,需要的朋友参考一下 前言 mcrypt 扩展已经过时了大约10年,并且用起来很复杂。因此它被废弃并且被 OpenSSL 所取代。 从PHP 7.2起它将被从核心代码中移除并且移到PECL中。

  • Node.js may deprecate APIs when either: (a) use of the API is considered to be unsafe, (b) an improved alternative API has been made available, or (c) breaking changes to the API are expected in a fut

  • 我已经创建了一个facebook应用程序,并检索了有效期为60天的用户访问令牌。 在Android系统中,有一些东西 public void onResume(){ super.onResume();facebook.extendedcesstokenifneeded(此,null);} 这将扩展accesstoken(如果它即将过期)。PHP中是否有类似的替代方案?因此,60天后,令牌将刷新,而

  • 问题内容: 除了看起来不太好以外,是否有其他替代方法可以在Java中实现切换案例。根据选择必须执行的方法,一组值会组合在一起。 问题答案: 想必您正在努力满足案件不变的要求。通常,这是代码气味,但是您可以做一些事情。您可能想提出并链接到另一个详细说明您为何尝试切换的问题。 在上面的示例中,您可能想要映射到“处理程序”,例如 然后,这一切都变成了查找。 同样,这有点气味,因此请发布一个说明原因的问题

  • 本文向大家介绍Ubuntu16.04.4LTS安装mininet遇到的问题及解决方案,包括了Ubuntu16.04.4LTS安装mininet遇到的问题及解决方案的使用技巧和注意事项,需要的朋友参考一下 Mininet Mininet 是一个轻量级软件定义网络和测试平台;它采用轻量级的虚拟化技术使一个单一的系统看起来像一个完整的网络运行相关的内核系统和用户代码,也可简单理解为 SDN 网络系统中的

  • 本文向大家介绍php实现cookie加密的方法,包括了php实现cookie加密的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了php实现cookie加密的方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的php程序设计有所帮助。