You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP7.2下Sagepay示例代码mcrypt转openssl的问题与解决

解决Sagepay PHP示例代码从mcrypt迁移到openssl的问题

我之前留意到Sagepay的官方PHP示例依赖已经被废弃的mcrypt扩展(PHP7.2及以上版本不再支持),在没收到官方回复的情况下,自己尝试把mcrypt调用替换成openssl,踩了不少坑后终于成功适配,分享一下过程和最终实现:

原mcrypt加密代码

Sagepay原本的加密逻辑是这样的:

$strIV = $strEncryptionPassword; 
//** add PKCS5 padding to the text to be encypted 
$strIn = addPKCS5Padding($strIn); 
//** perform encryption with PHP's MCRYPT module 
$strCrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $strEncryptionPassword, $strIn, MCRYPT_MODE_CBC, $strIV); 

踩坑的尝试过程

我一开始直接替换成openssl调用,但不管是启用OPENSSL_NO_PADDING,还是切换AES_192_CBC/AES_256_CBC模式,生成的加密串都和mcrypt版本的不一致(原mcrypt版本是通过Sagepay验证过的):

$strIV = $strEncryptionPassword; 
$strCrypt = openssl_encrypt($strIn,'AES-128-CBC',$strIV,$options=OPENSSL_RAW_DATA); 
//** perform hex encoding and return 
return "@" . bin2hex($strCrypt); 

成功的openssl替代实现

经过反复调试,我找到了和原逻辑完全兼容的参数组合,以下是替换后的加密和解密函数:

加密函数:NEWencryptAndEncode

define('SESS_CIPHER','AES-128-CBC');
function NEWencryptAndEncode($strIn) {
    global $strEncryptionType ,$strEncryptionPassword;
    if ($strEncryptionType=="XOR") {
        //** XOR encryption with Base64 encoding **
        return base64Encode(simpleXor($strIn,$strEncryptionPassword));
    } else {
        //** AES encryption, CBC blocking with PKCS5 padding then HEX encoding - DEFAULT **
        //** use initialization vector (IV) set from $strEncryptionPassword
        $strIV = $strEncryptionPassword;
        //** add PKCS5 padding to the text to be encypted
        $strIn = addPKCS5Padding($strIn);
        //** perform encryption with PHP's Openssl module
        $strCrypt = openssl_encrypt($strIn, SESS_CIPHER,$strIV,$options=OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,$strIV);
        //** perform hex encoding and return
        return "@" . bin2hex($strCrypt);
    }
}

解密函数:NEWdecodeAndDecrypt

function NEWdecodeAndDecrypt($strIn) {
    global $strEncryptionPassword;
    if (substr($strIn,0,1)=="@") {
        //** HEX decoding then AES decryption, CBC blocking with PKCS5 padding - DEFAULT **
        //** use initialization vector (IV) set from $strEncryptionPassword
        $strIV = $strEncryptionPassword;
        //** remove the first char which is @ to flag this is AES encrypted
        $strIn = substr($strIn,1);
        //** HEX decoding
        $strIn = pack('H*', $strIn);
        //** perform decryption with PHP's Openssl module
        return openssl_decrypt($strIn, SESS_CIPHER,$strIV,$options=OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,$strIV);
    } else {
        //** Base 64 decoding plus XOR decryption **
        return simpleXor(base64Decode($strIn),$strEncryptionPassword);
    }
}

关键适配要点

  • 保留原逻辑的PKCS5 padding预处理,同时在openssl调用时指定OPENSSL_ZERO_PADDING,避免openssl自动添加其他格式的padding导致结果不一致
  • 加密和解密都显式传入IV参数(和原mcrypt逻辑一致,使用加密密码作为IV)
  • 启用OPENSSL_RAW_DATA确保输出为原始二进制数据,再进行hex编码,和原流程完全对齐

内容的提问来源于stack exchange,提问作者brian read

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:03:29