PHP无法解密JSON请求体中Base64编码的公钥加密字符串
RSA解密Base64编码密文失败问题解决
核心错误:变量误用导致解码完全错误
看你贴的测试代码,一眼就能看到问题:
$decodedCipher = base64_decode($cipherStream); // 此处应为base64_decode($encodedCipher)
你把原始二进制密文直接拿去做Base64解码了,而不是用刚编码好的$encodedCipher。原始二进制数据本身不是Base64格式,解码后必然是乱码,openssl自然报PKCS解码错误——因为解密用的根本不是正确的密文。
至于十六进制转换能成功,是因为bin2hex把二进制转成了纯文本的十六进制字符串,hex2bin又精准转回到原始二进制,整个过程没有数据损失,所以解密正常。
实际场景中Base64传输的潜在坑(修正变量后仍要注意)
如果修正变量后还是有问题,大概率是Base64在传输/序列化过程中被篡改了,常见的坑:
- 特殊字符被转义:Base64里的
+、/在URL传输或某些框架的自动处理中可能被转成空格或其他字符,导致解码后数据残缺。 - 多余换行符:有些工具(比如openssl的
base64命令)会给编码结果加换行,要是这些换行被保留在JSON里,解码后会多出无效字节,破坏密文结构。 - 填充缺失:Base64末尾的
=是填充字符,要是传输时被误删,解码会不完整。
正确的处理流程
客户端侧
- 用公钥加密原始字符串,得到二进制密文
- 调用标准Base64编码(不要加换行,比如PHP的
base64_encode、JavaScript的btoa/Buffer.from().toString('base64')) - 将编码后的字符串直接放入JSON请求体发送,JSON会自动处理特殊字符的转义,不用额外操作
服务端侧
- 解析JSON请求体,取出Base64密文字符串
- 用
base64_decode($str, true)解码:第二个参数设为true,如果解码失败会返回false,方便快速排查 - 加载私钥后调用解密,确保填充模式和加密时一致(
openssl rsautl -encrypt默认用PKCS1填充,对应PHP的OPENSSL_PKCS1_PADDING)
修正后的测试代码
// 读取加密文件内容 $cipherFile = fopen("<加密文件路径>","r"); $cipherStream = fread($cipherFile,8192); fclose($cipherFile); // 模拟客户端的Base64编码 $encodedCipher = base64_encode($cipherStream); // 模拟服务端接收后解码(这里修正了变量) $decodedCipher = base64_decode($encodedCipher, true); if (!$decodedCipher) { Log::error("Base64解码失败"); return null; } // 加载私钥 $privateKeyFile = fopen("<私钥文件路径>","r"); $privateKeyStream = fread($privateKeyFile,8192); fclose($privateKeyFile); $pkey = openssl_pkey_get_private($privateKeyStream,"<私钥密码>"); if (!$pkey) { Log::error("Error extracting private key"); return null; } // 解密 if (!openssl_private_decrypt($decodedCipher, $decryptedString, $pkey, OPENSSL_PKCS1_PADDING)) { Log::error("Error decrypting keys " . openssl_error_string()); return null; } // 输出解密结果 var_dump($decryptedString);
内容的提问来源于stack exchange,提问作者Ryan H
相关产品推荐
相关产品推荐

