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

作者站长头像
站长
· 阅读数 4
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库,这样实现,输出的结果不一致是什么原因呢?

回复
1个回答
avatar
test
2024-06-25

前人挖坑,后人遭殃。

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 就好了。

<?php

function 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 获得的结果。

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容