国密即国家密码局认定的国产密码算法。主要有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)