「宏结算支付国密SM2签名和国密SM4」PHP对接API
发表于更新于
广州
开发PHP国密算法「宏结算支付国密SM2签名和国密SM4」PHP对接API
❄️2winter
最近接触到宏结算的API对接,第一次使用国密算法签名,记录一下遇到的问题。
宏结算使用SM2签名,SM4加密
示例代码只有java版本,没有其他版本,我们使用PHP,于是开始寻找支持的方式,最后openssl支持但是有限制,后来发现和招商银行的签名流程差不多,参考其他关于招商对接的流程,完成了签名和加密对接。
首先是使用PHP SM2签名
拿到手的私钥和公钥是Base64编码的,需要特殊处理一下,另外安装这个sm2加密库,lpilp/guomi,里面涵盖了对接API的全部方法。
下面是PHP版本实现SM2签名和SM4加密。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| require_once __DIR__ . '/../vendor/autoload.php';
use Rtgm\sm\RtSm2; use Rtgm\sm\RtSm4;
class ApplyHJS {
private const API_URL = 'api.xxx.com'; private const API_PRE = '/xxx'; private const USER_CODE = 'xxx'; private const PK = 'xxx'; private const PUK = 'xxx'; private const BUK = 'xxxx';
private $sm4; private $sm2; private $userId;
function __construct() {
$this->sm2 = new RtSm2("base64"); $this->sm4 = new RtSm4(base64_decode(self::BUK)); $this->userId = sprintf('%-016s', self::USER_CODE); }
function signAndCrypt($data) {
$privateKey = base64_decode(self::PK); $privateKey = unpack("H*", $privateKey)[1]; $sign = $this->sm2->doSign($data, $privateKey, $this->userId); $sign = base64_decode($sign); $point = \FG\ASN1\ASNObject::fromBinary($sign)->getChildren(); $pointX = $this->formatHex($point[0]->getContent()); $pointY = $this->formatHex($point[1]->getContent()); $sign = $pointX . $pointY; $sign = base64_encode(hex2bin($sign)); $data = str_replace('__signature_sigdat__', $sign, $data); $sm4 = new RtSm4(base64_decode(self::BUK)); $encryptData = $sm4->encrypt($data, 'sm4-cbc', $this->userId, "base64");
return $encryptData; }
function decryptSign($decryptData) {
$json = $this->sm4->decrypt($decryptData, $type = 'sm4-cbc', $this->userId, $formatInput = 'base64'); $data = json_decode($json, true);
return $data; }
function formatHex($dec) { $hex = gmp_strval(gmp_init($dec, 10), 16); $len = strlen($hex); if ($len == 64) { return $hex; } if ($len < 64) { $hex = str_pad($hex, 64, "0", STR_PAD_LEFT); } else { $hex = substr($hex, $len - 64, 64); } return $hex; }
}
|
宏结算平台呢,基本上搜索不到任何相关的文档和手册,拿到手的所谓API对接,也只是一个内部使用的word版本,简单的java示例。对接很麻烦,文档也没有解释和说明。最终在本地部署了Java版本的示例运行起来才确定是可以用。不然都怀疑用不了。
❄️2winter
ReactNative FullStack Developer
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ❄️2winter!