qhweb/phpsm

PHP 国密(SM2,SM3,SM4)

Installs: 3

Dependents: 1

Suggesters: 0

Security: 0

pkg:composer/qhweb/phpsm

1.0.0 2025-11-24 10:01 UTC

This package is auto-updated.

Last update: 2025-11-24 10:03:15 UTC


README

php版本的国密sm2的签名算法,非对称加解密算法(非对称加密刚上线,目前测试无问题,不能保证兼容其他语言,有问题可以提issues),sm3的hash,hmac, sm4的对称加解密,要求PHP7+,打开gmp支持 目前如果服务器配套的使用的是openssl 1.1.1x, 目前到1.1.1.l(L) ,sm3,sm4都可以直接用openssl_xxx系列函数直接实现,不必大量的代码,但不支持sm2的签名

使用(how to use)

  • composer require qhweb/phpsm
  • please make sure you upgrade to Composer 2+
  • 测试是在php 8.2.9下做的

SM2

  • 签名验签算法主体基于PHPECC算法架构,添加了sm2的椭圆参数,
  • 参考了 https://github.com/ToAnyWhere/phpsm2 童鞋的sm2验签算法,密钥生成算法
  • 添加了签名算法, 支持sm2的16进制,base64公私钥的签名,验签算法
  • 支持从文件中读取pem文件的签名,验签算法
  • 添加了sm2的非对称加密的算法,但速度一般,有待优化,不能保证兼容所有语言进行加解密,目前测试了js, python的相互加解密
  • sm2的加密解密算法在openssl 1.1.1的版本下自带的函数中暂无sm2的公钥私钥的加密函数,得自己实现,建议使用C,C++的算法,打包成PHP扩展的方式
  • 由于 openssl没有实现sm2withsm3算法,用系统函数无法实现签名及证书的自签名分发

SM3

SM4

  • 该算法直接封装使用 https://github.com/lizhichao/sm 的sm4算法, 同时该项目支持 sm3,sm4 ,可以composer安装
  • 由于sm4-ecb, sm4-cbc加密需要补齐,项目lizhichao/sm项目未做补齐操作,这里封装的时候,针对这两个算法做了补齐操作, 其他如sm4-ctr,sm4-cfb,sm4-ofb等,可以直接用
  • 在openssl 1.1.1下可使用系统的函数,已支持sm4-cbc,sm4-cfb,sm4-ctr,sm4-ecb,sm4-ofb, 详见openssl_tsm4.php

总结

测试实例代码

<?php
require '../vendor/autoload.php';

use qhwwb\phpsm\sm\SM2;
use qhwwb\phpsm\sm\SM3;
use qhwwb\phpsm\sm\SM4;
// 使用示例
try {
    $key = '1234567890abcdef'; // 16 字节
    $iv = 'abcdefghijklmnop';  // 16 字节

    $sm2 = new SM2();
    echo "=== SM3 ===\n\n";
    echo '普通加密:'.SM3::hash('admin123'). "\n";
    echo '填充加密:'.SM3::hmac('admin123','12345'). "\n";
    // 1. 生成密钥对
    echo "=== SM2密钥生成 ===\n\n";
    // [$privateKey, $publicKey] = $sm2->generatekey();
    $privateKey = '2bc313584c9aece21b1c3cf7b8b7fa5561612d82c2b823067452ff396edcaec9';
    $publicKey = '0423652d9339b008e8861eec73633ea0c50726d5f478f6db9699cbe3f1a9052f4bfbc345600b53dfd6bac616cb9909e89bdfd094163669d7ed191b51626baa26a0';
    echo "私钥:\n" . $privateKey . "\n";
    echo "公钥:\n" . $publicKey . "\n";
    
    // 2. 测试数据
    $testData = "hello world!";
    echo "原始数据: " . $testData . "\n";
    
    // 3. 加密解密测试
    echo "=== SM2加密解密测试 ===\n\n";
    $encryptResult = $sm2->doEncrypt($testData, $publicKey);
    echo "加密结果: " . $encryptResult. "\n";


    $decryptResult = $sm2->doDecrypt($encryptResult,$privateKey);
    echo "解密结果: " . $decryptResult . "\n";
    
    // 4. 数字签名测试
    echo "=== SM2数字签名测试 ===\n\n";
    $signResult = $sm2->doSign($testData,$privateKey);
    echo "签名结果: " . $signResult . "\n";
    
    // 5. 签名验证测试
    $verifyResult = $sm2->verifySign($testData, $signResult,$publicKey);
    echo "签名验证: " . ($verifyResult ? "成功" : "失败") . "\n";
    
    echo "=== SM4测试 ===\n\n";
    $sm4 = new SM4($key);
    $types = ['cbc','ecb','ctr','ofb','cfb'];
    $data = json_encode(["a"=>1,"b"=>2]);
    foreach ($types as  $type) {
        $encryptData = $sm4->encrypt($data,'sm4-'.$type,$iv);
        $decryptData = $sm4->decrypt($encryptData,'sm4-'.$type,$iv);
        echo "=== [$type] ===\n";
        echo $type."加密结果: " . $encryptData . "\n";
        echo $type."解密结果: " . $decryptData . "\n";
    }
    

} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
}

快捷函数

  • SM2随机密钥(hex): createSm2Key()
  • SM2随机密钥(PEM): createSm2KeyPem()
  • SM2公钥加密: sm2Encrypt($str,$privateKey)
  • SM2私钥解密: sm2Decrypt($str,$privateKey)
  • SM2签名: sm2Sgin($str,$privateKey, $userId = null)
  • SM2验签: sm2VerifySign($str,$sign, $publicKey, $userId = null)
  • SM2签名: sm2SignOut($str, $privateKeyFile, $userId = null) 私钥文件签名
  • SM2验签: sm2VerifySignOut($str, $sgin, $publickeyFile, $userId = null) 公钥文件验签
  • SM3加密: sm3($str,$key='') $key为加密盐
  • SM4加密: sm4Encrypt($str, $type = 'sm4', $iv = '', $key='1234567890abcdef',$formatOut = 'hex') $type加密模式'sm4-*'(cbc,ecb,ctr,ofb,cfb)
  • SM4解密: sm4Decrypt(string $str, $type = 'sm4', $iv = '', $key='1234567890abcdef',$formatInput = 'hex') $type加密模式'sm4-*'(cbc,ecb,ctr,ofb,cfb)