Sage Pay/Opayo Form 集成 - 用 openssl 替换 mcrypt

问题描述

我们使用 Sage Pay / Opayo 表单集成将客户订单传递给 Sage Pay 进行付款,然后处理返回的报告。 Sage Pay 的示例代码依赖于 PHP 7.2 不再支持PHP mcrypt 函数,因此我们需要将脚本更新为 OpenSSL。

这里有一篇很棒的文章介绍了加密: Upgrade mcrypt to OpenSSL encryption in SagePay form

  • 这对我来说很好用:
    function encryptAes_new ($string,$key) {
      $key = str_pad($key,16,"\0"); # if supplied key is,or may be,less than 16 bytes
      $crypt = openssl_encrypt($string,'aes-128-cbc',$key,OPENSSL_RAW_DATA,$key);
      // Perform hex encoding and return.
      return "@" . strtoupper(bin2hex($crypt));
    }

...但我找不到匹配的代码来修复解密功能。​​

当前代码为:


    function decryptAes($strIn,$password)
    {
        // HEX decoding then AES decryption,CBC blocking with PKCS5 padding.
        // Use initialization vector (IV) set from $str_encryption_password.
        $strInitVector = $password;
    
        // Remove the first char which is @ to flag this is AES encrypted and HEX decoding.
        $hex = substr($strIn,1);
    
        $strIn = pack('H*',$hex);
    
        // Perform decryption with PHP's MCRYPT module.
        $string = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,$password,$strIn,MCRYPT_MODE_CBC,$strInitVector);
        return removePKCS5Padding($string);
    }

有人可以帮忙提供一个 OpenSSL 版本吗?

解决方法

解密时,必须先去掉@前缀,然后进行十六进制解码,最后才能进行解密。 openssl_decrypt() 隐式删除填充,因此不需要显式删除。这是在下面的 decryptAes_new() 中实现的:

<?php
function encryptAes_new ($string,$key) {
    $key = str_pad($key,16,"\0"); # if supplied key is,or may be,less than 16 bytes
    $crypt = openssl_encrypt($string,'aes-128-cbc',$key,OPENSSL_RAW_DATA,$key);
    // Perform hex encoding and return.
    return "@" . strtoupper(bin2hex($crypt));
}

function decryptAes_new($string,"\0"); 
    $binary = hex2bin(substr($string,1));
    return openssl_decrypt($binary,$key);
}

$plaintext = 'The quick brown fox jumps over the lazy dog';
$key = '0123456789012345';
$ciphertext = encryptAes_new($plaintext,$key);
$decrypted = decryptAes_new($ciphertext,$key);
print('Ciphertext: ' . $ciphertext . PHP_EOL);
print('Plaintext:  ' . $decrypted . ' - Size: ' . strlen($decrypted) . PHP_EOL);
?>

产生输出:

Ciphertext: @3089E6BC224BD95B85CF56F4B967118AAA4705430F25B6B4D953188AD15DD78F3867577E7D58E18C9CB340647C8B4FD8
Plaintext:  The quick brown fox jumps over the lazy dog - Size: 43

查看解密后的明文长度,43个字节,显示已自动去除padding。