phpseclib 2 RSA解密正常但phpseclib 3 RSA解密异常如何解决
问题复现代码
- phpseclib 2 示例代码 - 运行正常
use phpseclib\Crypt\RSA; $rsa = new RSA(); $rsa->loadKey($PRIVATE_KEY); $key = $rsa->decrypt(base64_decode($a));
- phpseclib 3 示例代码 - 运行异常
use phpseclib3\Crypt\PublicKeyLoader; $private = PublicKeyLoader::load($PRIVATE_KEY); $key = $private->decrypt(base64_decode($a));
两段代码逻辑均为加载RSA私钥后,对base64解码后的密文做解密操作,逻辑完全一致但运行结果不同。
版本不兼容的核心原因
phpseclib 3对RSA加解密的默认规则做了破坏性变更,和v2的默认行为不兼容:
- 填充模式默认值不同:v2解密时会自动遍历所有支持的填充模式(包括PKCS#1 v1.5、各哈希算法的OAEP填充)做匹配尝试,不需要手动指定;v3默认仅使用SHA256哈希的OAEP填充,不会自动降级尝试其他填充,密文填充和默认值不匹配时会直接解密失败。
- 校验严格度不同:v2对格式不规范的密钥、密文会自动做容错修正,v3默认开启严格格式校验,不符合ASN.1规范的输入会直接返回解密失败。
绝大多数跨版本解密失败的场景,都是因为旧业务生成的RSA密文采用了PKCS#1 v1.5填充(旧系统最常用的RSA加密填充标准),和v3默认的OAEP填充不匹配导致的。
修复方案
在v3中解密前显式指定和v2一致的填充模式即可,和旧逻辑对齐的代码如下:
use phpseclib3\Crypt\PublicKeyLoader; use phpseclib3\Crypt\RSA; // 加载私钥,若密钥格式不规范可将第二个参数设为false关闭严格校验 $private = PublicKeyLoader::load($PRIVATE_KEY); // 显式指定填充模式为PKCS#1 v1.5,和v2默认行为对齐 $private = $private->withPadding(RSA::ENCRYPTION_PKCS1); $key = $private->decrypt(base64_decode($a));
如果确认密文是OAEP填充但解密失败,可根据加密端使用的哈希算法替换对应填充常量:
- 加密端用SHA1哈希的OAEP:
RSA::ENCRYPTION_OAEP_WITH_SHA1 - 加密端用MD5哈希的OAEP:
RSA::ENCRYPTION_OAEP_WITH_MD5 - 加密端用SHA512哈希的OAEP:
RSA::ENCRYPTION_OAEP_WITH_SHA512
内容的提问来源于stack exchange,提问作者Jayendra Matarage
相关产品推荐
相关产品推荐

