在 PHP 中将 mcrypt_encrypt 转换为 openssl_encrypt

Posted

技术标签:

【中文标题】在 PHP 中将 mcrypt_encrypt 转换为 openssl_encrypt【英文标题】:Converting mcrypt_encrypt to openssl_encrypt in PHP 【发布时间】:2021-09-22 06:16:41 【问题描述】:

由于 mcrypt_encryptphp 8 中删除,我需要将以下代码转换为使用 openssl_encrypt

function encryptValue($input,$sKey)
   
    $key = hex2bin($sKey);
    
    $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
    $pad = $block - (strlen($input) % $block);
    $input .= str_repeat(chr($pad), $pad);
    
    $encrypted_text = bin2hex(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $input, MCRYPT_MODE_ECB));  

    return $encrypted_text;

我将其替换为以下内容:

function encryptData($input, $sKey)
    
        $key= hex2bin($sKey);

        $encrypted_text = bin2hex(openssl_encrypt($input, 'AES-256-ECB', $key, OPENSSL_RAW_DATA));
        return $encrypted_text;
    

由于 openssl 做了默认填充,我没有像在原始代码中那样填充明文。我相信密钥正在转换为二进制。如果我省略了两个代码的密钥转换,那么我会得到相同的加密文本。但是如果我使用密钥转换,那么密文就不一样了。

如果我从两者中删除以下代码,则两者都返回相同的加密文本。

$key= hex2bin($sKey);

但如果没有这个,它将无法与外部 API 一起使用。

【问题讨论】:

您的代码 "$key .= chr(hexdec($sKey[$i].$sKey[$i+1]))" 是“十六进制字符串到字符串”转换器,例如输入“31323334353637386162636465666768”被转换为“12345678abcdefgh”。现在一切都取决于 key length - 使用我的示例字符串时,您有一个 16 个字符/字节长的 AES 密钥,它适用于 AES-128 而不是 AES -256 与您在函数中使用的一样。在您的 openssl 代码中使用双倍输入密钥将需要 AES-256。如果我的回答没有解决您的问题,如果您可以提供带有结果密文的示例密钥,这可能会有所帮助。 $inputVal 在两个 sn-ps 中都没有定义。这必须更改为$input。可能是复制/粘贴问题。修复此问题后,两个代码都返回相同的密文(只要两个代码一致地使用密钥转换)。顺便说一句,密钥转换在功能上与hex2bin() 相同。 @MichaelFehr 示例密钥:2ca8a887d4cc71dd68785c2ebe11a6aa 这是一个真正的密钥。这通过 hex2bin 函数,它返回一些 unicode 字符。然后将其传递给加密函数。另外,我将 AES-256-ECB 与 openssl 一起使用,因为这是密钥大小。 @user9014097 编辑了问题。不使用密钥转换时,hex2bin 都返回相同的密文。但是当两者都使用密钥转换时,密文是不同的。不知道发生了什么。并且它需要密钥转换,因为接收 API 可能也在解密中使用它。 同样在第一个 sn-p 中,将 $inputVal 更改为 $input。目前您不使用填充明文。 【参考方案1】:

您的代码"$key .= chr(hexdec($sKey[$i].$sKey[$i+1]))" 是“十六进制字符串到字符串”转换器,例如输入“31323334353637386162636465666768”被转换为“12345678abcdefgh”。

现在一切都取决于密钥长度 - 使用我的示例字符串时,您有一个 16 个字符/字节长的 AES 密钥,适用于 AES-128非 AES-256 就像你在函数中使用的那样。

在您的 openssl 代码中使用双输入密钥需要 AES-256

如果我的回答没有解决您的问题,如果您可以提供带有结果密文的示例密钥,这可能会有所帮助。

【讨论】:

以上是关于在 PHP 中将 mcrypt_encrypt 转换为 openssl_encrypt的主要内容,如果未能解决你的问题,请参考以下文章

PHP 7.2中mcrypt_encrypt的精确替代

PHP 7.2 中 mcrypt_encrypt 的完全替代品

.NET WebService 加密 -> PHP 解密错误:mcrypt_encrypt(): IV 参数必须与块大小一样长

php使用内置的mcrypt_encrypt和mcrypt_decrypt进行字符串加密解密

CryptoJS 中 CFB 模式中的 mcrypt_encrypt 函数

为啥 mcrypt_encrypt() 将二进制字符放在我的字符串末尾?