前端用CryptoJS RSA加密后服务端解密报padding错误怎么办?
我用CryptoJS的RSA.encrypt加密字符串,传到PHP服务端用openssl_private_decrypt解密时一直报错”error:0407106B:RSA routines:RSA_padding_check_PKCS1_type_1:number too small”。前后端都用了PKCS1Padding,密钥对是用openssl生成的,前端用的是PEM格式公钥,后端私钥是.pem文件直接读取的。试过base64编码解码都不行,加密后的数据是这样的:Tk1aQzJFQjA...
// 前端加密代码
const encrypted = CryptoJS.RSA.encrypt(
message,
publicKey,
{padding: CryptoJS.pad.Pkcs1Padding}
).toString();
服务端PHP直接用了官方示例代码,参数都试过true/false切换。是不是密钥格式有问题?或者加密方式有差异?
调试看看,问题出在前端加密后的数据格式上。CryptoJS.RSA.encrypt返回的结果是Base64编码的字符串,而PHP的openssl_private_decrypt需要的是原始的二进制数据。所以你需要在服务端解密前,先把接收到的数据从Base64转回二进制。
解决方案分两步走:
第一步,前端代码不用改太多,但要确保加密后的结果确实是Base64编码的。你的前端代码看起来没问题,加密后调用toString()已经是Base64了。
第二步,服务端PHP解密时,先对接收到的数据做Base64解码,然后再传给openssl_private_decrypt。代码可以这么写:
另外,建议你确认一下公钥和私钥的格式是否正确。前端用的公钥必须是PEM格式的,并且去掉换行符或特殊字符后再使用。如果还是有问题,可以用工具(比如OpenSSL命令)验证一下密钥对是否匹配。
调试这种跨语言加密解密问题挺烦人的,尤其是填充模式和数据格式不一致的时候。按上面的方法调整一下,应该就能解决问题了。