当前位置: 首页 > news >正文

PHP如何解决使用国密SM4解密Base64数据错误问题?(基于lpilp/guomi)

最近遇到与java对接的时候接收的base64数据,SM4解密一部分正常、一部分乱码乱码的问题,最后仔细看了接收到的base64数据,发现是PHP接收url中的数据问题。

一、下面展示下解决问题之前的问题:

首先、把需要加密的json串整理出来,进行SM4加密

其次、将加密后的base64串添加到接口请求工具中data参数值中

再次、打印PHP接收到的base64数据串

最后、用接收到的数据串进行SM4解密,打印出来发现只解析了前面一点点,后面的是乱码

解决思路:

重点在以下几点:

1、接收到的base64数据;

2、lpilp/guomi扩展包中的SM4加密解密的方法;

思考:扩展包的加密解密方法肯定是没问题的,但是也不保证没有问题,细扒代码,发现是在解密base64_decode数据后,用解密方法解出来后就有问题了,解密方法之前用过,可以肯定没有问题,那就是传入的解密数据有问题了。

发现问题:仔细一看打印出来的加密后的数据和PHP接收到的数据不一样,接收到的数据中有空格。

原因是:+号在 URL 中被浏览器/前端自动转换成空格(空格编码成 %20),而后端 request()->all() 又把空格保留下来,最终造成 Base64 字符串被破坏。

解决办法:将接收到的数据中的空格转换成+号还原。再去调用解密方法

$cipher = str_replace(' ', '+', $cipher);   // 把空格全部还原成 +
$plain  = (new RtSm4($key))->decrypt($cipher, 'sm4-ecb', '', 'base64');

将数据顺利解密,出来的结果如下:

与加密数据一致。

附件:SM4和SM2加密解密的公共调用方法

<?phpnamespace App\Support;
use Rtgm\sm\RtSm4;
use Rtgm\sm\RtSm2;
use Rtgm\util\MyAsn1;class GuomiHelper
{/*** 生成安全随机数(不超过128位)** @param int $length 随机数长度,最大128位* @return string*/public static function generateNonce($length = 32){$length = min($length, 128);$bytes = random_bytes(ceil($length / 2));return substr(bin2hex($bytes), 0, $length);}/*** 使用 key 进行 SM4 ECB 加密(在用)** @param string $data* @param string $key* @return string*/public static function sm4EcbEncrypt($data, $key) {//dump($data);// 使用示例// $key = hex2bin("30ca0d013a9a782fe4c6b4c30d3e208c");// $data = "18900112233"; 运行结果;571d9decc557bd9d466f6c90df328bb4$key = hex2bin($key);//将十六进制字符串转换为二进制数据$sm4 = new RtSm4($key);$ciphertext = $sm4->encrypt($data, 'sm4-ecb','','base64');return $ciphertext;}/*** 使用 key 进行 SM4 ECB 解密(在用)* * @param string $data* @param string $key* @return string*/public static function sm4EcbDecrypt($data, $key) {// 移除base64编码中的空格换行$key = hex2bin($key);//将十六进制字符串转换为二进制数据 $data, $type = 'sm4', $iv = '', $formatInput = 'hex'$sm4 = new RtSm4($key);$plaintext = $sm4->decrypt($data, 'sm4-ecb','','base64');return $plaintext;}/*** 账户公钥SM2加密(在用)** @param string $data* @param string $publicKey* @return string*/public static function rtSm2Encrypt($plaintext, $publicKeyBase64) {    // 从DER格式中提取公钥内容(去除ASN.1头部)$publicKeyHex =  MyAsn1::decode($publicKeyBase64,'base64');// 创建SM2实例$sm2 = new RtSm2();// 执行加密(使用公钥的十六进制格式)$ciphertextBin = $sm2->doEncrypt($plaintext, $publicKeyHex[1]);return '04'.$ciphertextBin;}/*** 账户私钥SM2解密(在用)*/public static function rtSm2Decrypt($ciphertext, $privateKey) {// 创建SM2实例$sm2 = new RtSm2();$m2DecryptData = $sm2->doDecrypt($ciphertext,$privateKey);return $m2DecryptData;}/*** 账户公钥SM2验签* 使用 SM2 非对称加密算法结合 SM3 哈希算法对给定的数据进行签名验证* @param string $publicKeyString:十六进制字符串表示的 SM2 公钥。* @param string $notifyString:需要验证签名的原始数据字符串。* @param string $signString:十六进制字符串表示的签名数据。* @return string*/public static function sm2WithSM3Verify($publicKeyString, $notifyString, $signString){$sm2 = new RtSm2();$result = $sm2->verifySign($notifyString, $signString, $publicKeyString);return $result;}
}

http://www.xdnf.cn/news/1440523.html

相关文章:

  • 协议分析基础
  • 以技术共享点燃全球能源变革新引擎的智慧能源开源了
  • 低代码革命遇瓶颈?这个“套娃神技“才是破局关键!
  • 在Excel和WPS表格中隔多行插入一个空白行
  • 多场景对练数据的 Excel 横向导出方案(EasyExcel 动态表头实践)
  • 【XR硬件系列】Vivo Vision 与 Apple VisionPro 深度技术对比:MR 时代的轻量化革命与生态霸权
  • 单元测试数据库回滚问题
  • Android音频学习(十六)——CreateTrack
  • 资产管理还靠Excel?深度体验系统如何让企业高效数字化升级!
  • 自然语言处理深层语义分析中公理化体系的可行性、挑战与前沿进展
  • php:PHP 8 新特性深度解析与实战应用:提升开发效率的关键技巧
  • 为何 React JSX 循环需要使用 key
  • 一文弄懂C/C++不定参数底层原理
  • Zygote 进程启动流程
  • 视频判重需求:别为同一内容花两次钱!
  • 涨了一倍多的顺丰同城,还能继续做大即时零售基建的蛋糕吗?
  • HTML5 标题标签、段落、换行和水平线
  • 光谱相机的探测器类型
  • 相机在两个机械臂上安装方式比较
  • 字节跳动后端 一面凉经
  • 单片机:GPIO、按键、中断、定时器、蜂鸣器
  • 知微传感Dkam系列3D相机SDK例程篇:CSharp连接相机及保存数据
  • Debezium日常分享系列之:Debezium 3.3.0.Alpha2发布
  • Gemini CLI源码解析:Agent与上下文管理实现细节
  • Airsim 笔记:Python API 总结
  • ESXI8多网卡链路聚合
  • 渗透测试中的常见误区与最佳实践
  • 【LeetCode 热题 100】72. 编辑距离——(解法一)记忆化搜索
  • DBSCAN 密度聚类分析算法
  • 【ProtoBuf 】C++ 网络通讯录开发实战:ProtoBuf 协议设计与 HTTP 服务实现