国密SM2/3/4 PHP


国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位。国密算法是指国家密码管理局认定的一系列国产密码算法,包括SM1-SM9以及ZUC等。其中

  • SM1、SM4、SM5、SM6、SM7、SM8、ZUC等属于对称密码
  • SM2、SM9等属于公钥密码 (非对称加密)
  • SM3属于单向散列函数。

目前我国主要使用公开的SM2、SM3、SM4作为商用密码算法。 其中SM1、SM7算法不公开,调用该算法时,需要通过加密芯片的接口进行调用.

  • SM2是基于椭圆曲线的公钥密码算法,包括用于数字签名的SM2-1、用于密钥交换的SM2-2和用于公钥密码的SM2-3。
  • SM3是能够计算出256比特的散列值的单向散列函数,主要用于数字签名和消息认证码。
  • SM4是属于对称密码的一种分组密码算法,分组长度和密钥长度均为128比特。

使用经验

  • 一般数据发送端都是用SM4对数据内容加密,使用SM3对内容进行摘要,再使用SM2对摘要进行签名。

  • 一般接收端,先用SM2对摘要进行验签,验签成功后就做到了防抵赖,对发送过来的内容进行SM3摘要,看下生成的摘要和验签后的摘要是否一致,用于防篡改。

  • 另外SM4在加密解密需要相同的密钥,这个我们可以通过编写密钥交换模块实现生成相同的密钥。用于SM4对称加密。

关于非对称还要注意几点:

(1)公钥是通过私钥产生的;

(2)公钥加密,私钥解密是加密的过程

(3)私钥加密,公钥解密是签名的过程;

由于SM1、SM4加解密的分组大小为128bit,故对消息进行加解密时,若消息长度过长,需要进行分组,要消息长度不足,则要进行填充。


SM2算法:(非对称加密)

SM2可以理解为国产RSA。非对称加密,基于ECC。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。

SM2椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,包括SM2-1椭圆曲线数字签名算法,SM2-2椭圆曲线密钥交换协议,SM2-3椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。SM2算法与RSA算法不同的是,SM2算法是基于椭圆曲线上点群离散对数难题,相对于RSA算法,256位的SM2密码强度已经比2048位的RSA密码强度要高,但运算速度快于RSA。

<?php
require_once '../vendor/autoload.php';
use Rtgm\sm\RtSm2;

$publicKey = '043d9d4cc71a285af936b36880fd4d6155c22957cd2c84ea313469065207fb951b9ef1db79d69af8886e91e833da1ebc6bfdde86e70f52923d6e042eaa147624c7'; // 公钥
$privateKey = 'a7763cd4fe7db2a2146fc09bf2d5e5a30e10c51b7e4bed00b3a26ec79ba78ff3'; // 私钥
$publicfile = "./data/sm2pub.pem";
$privatefile = "./data/sm2.pem";
$userId = '1234567812345678';
$document = "我爱你ILOVEYOU!";

define('GK',1);
define('SIGN',1);
define('SIGNPEM',1);
//返回的签名16进制还是base64, 目前可选hex,与base64两种
// __construct($formatSign='hex', $randFixed = true) 
$sm2 = new RtSm2('base64',true);


if(GK){
    echo "\n----------生成明文密钥对--------------------------\n";
    print_r($sm2->generatekey()); //生成明文密钥
    echo "\n----------生成pem密钥对--------------------------\n";
    print_r($sm2->generatePemkey()); //生成pem密钥,请放到相应的文件中
}

if(SIGN){
    echo "\n---------明文密钥签名---------------------------\n";
    $sign = $sm2->doSign( $document, $privateKey, $userId);
    print_r($sign);
    echo "\n---------明文密钥验签---------------------------\n";
    var_dump($sm2->verifySign( $document, $sign, $publicKey, $userId ));
}

if(SIGNPEM){
    echo "\n---------PEM密钥签名---------------------------\n";
    $sign = $sm2->doSignOutKey( $document, $privatefile, $userId);
    print_r($sign);
    echo "\n---------PEM密钥验签---------------------------\n";
    var_dump($sm2->verifySignOutKey( $document, $sign, $publicfile, $userId ));
}

SM3算法:
SM3可以理解为国产MD5。消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。

<?php
require_once '../vendor/autoload.php';
use Rtgm\sm\RtSm3;
$sm3 = new RtSm3();
$data = '我爱你ILOVEYOU!';
print_r($sm3->digest($data,1));

SM3HMAC算法PHP实现:

// 需要实现hamc-sm3国密定制算法
// composer require axios/tools
// @see https://github.com/AxiosLeo/php-tools/tree/cd576f058db7b633750d62bb6d7d1840f0ab8d5e

$hmac = new HMac();
$hmac->registerAlgorithm('sm3', function ($str) {
  // SM3签名函数
  $sm3 = new SM3();
  $sm3->encode($str);
  return $sm3->getHex();
 });
$s_crypto= $hmac->count('sm3', $s_return, $this->Prvkey);

SM4算法:对称加密:
可以理解为国产AES。无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。

<?php
require_once '../vendor/autoload.php';
use Rtgm\sm\RtSm4;

$key = "0123456789abcdef";
$iv = '1234567887654321';

$sm4 = new RtSm4($key);

$data = '我1爱你ILOVEYOU!!!';
$data = str_repeat('abc',7);
//sm4 的ecb 与cbc加密有补齐(16*n)l
// sm4->encrypt($data, $type = 'sm4', $iv = '', $format = 'hex')
//  openssl_encrypt ,和服务器openssl版本,PHP版本有关,有些服务器可能不支持sm4-* 相关的对称加密算法,

echo "==== test sm4 sm4-cbc============";
echo "\nphp sm4:     ".$hex = $sm4->encrypt($data,'sm4',$iv); //default is cbc
echo "\nphp decode:  ".$sm4->decrypt($hex,'sm4',$iv,'hex');

echo "\n==== test sm4-ecb============";
echo "\nphp sm4-ecb: ".$hex = $sm4->encrypt($data,'sm4-ecb');
echo "\nphp decode:  ".$sm4->decrypt($hex,'sm4-ecb','','hex');

echo "\n==== test sm4-ofb============";
echo "\nphp sm4-ofb: ".$hex = $sm4->encrypt($data,'sm4-ofb',$iv);
echo "\nphp decode:  ".$sm4->decrypt($hex,'sm4-ofb',$iv,'hex');

echo "\n==== test sm4-cfb============";
echo "\nphp sm4-cfb: ".$hex = $sm4->encrypt($data,'sm4-cfb',$iv);
echo "\nphp decode:  ".$sm4->decrypt($hex,'sm4-cfb',$iv,'hex');

echo "\n==== test sm4-ctr============";
echo "\nphp sm4-ctr: ".$hex = $sm4->encrypt($data,'sm4-ctr',$iv);
echo "\nphp decode:  ".$sm4->decrypt($hex,'sm4-ctr',$iv,'hex');

参考文档:
国密招商银行对接 | Laravel China 社区 (learnku.com)

lpilp/phpsm2sm3sm4: php版本,支持国密SM2的签名算法,非对称加解密,SM3的hash, SM4的对称加解密 (github.com)

https://cloud.tencent.com/developer/article/2421525

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容