國密即國家密碼局認定的國產密碼算法。主要有SM1,SM2,SM3,SM4。密鑰長度和分組長度均為128位。國密算法是指國家密碼管理局認定的一系列國產密碼算法,包括SM1-SM9以及ZUC等。其中
- SM1、SM4、SM5、SM6、SM7、SM8、ZUC等屬于對稱密碼
- SM2、SM9等屬于公鑰密碼 (非對稱加密)
- SM3屬于單向散列函數(shù)。
目前我國主要使用公開的SM2、SM3、SM4作為商用密碼算法。 其中SM1、SM7算法不公開,調用該算法時,需要通過加密芯片的接口進行調用.
- SM2是基于橢圓曲線的公鑰密碼算法,包括用于數(shù)字簽名的SM2-1、用于密鑰交換的SM2-2和用于公鑰密碼的SM2-3。
- SM3是能夠計算出256比特的散列值的單向散列函數(shù),主要用于數(shù)字簽名和消息認證碼。
- SM4是屬于對稱密碼的一種分組密碼算法,分組長度和密鑰長度均為128比特。
使用經驗
一般數(shù)據發(fā)送端都是用SM4對數(shù)據內容加密,使用SM3對內容進行摘要,再使用SM2對摘要進行簽名。
一般接收端,先用SM2對摘要進行驗簽,驗簽成功后就做到了防抵賴,對發(fā)送過來的內容進行SM3摘要,看下生成的摘要和驗簽后的摘要是否一致,用于防篡改。
另外SM4在加密解密需要相同的密鑰,這個我們可以通過編寫密鑰交換模塊實現(xiàn)生成相同的密鑰。用于SM4對稱加密。
關于非對稱還要注意幾點:
(1)公鑰是通過私鑰產生的;
(2)公鑰加密,私鑰解密是加密的過程
(3)私鑰加密,公鑰解密是簽名的過程;
由于SM1、SM4加解密的分組大小為128bit,故對消息進行加解密時,若消息長度過長,需要進行分組,要消息長度不足,則要進行填充。
SM2算法:(非對稱加密)
SM2可以理解為國產RSA。非對稱加密,基于ECC。該算法已公開。由于該算法基于ECC,故其簽名速度與秘鑰生成速度都快于RSA。
SM2橢圓曲線公鑰密碼算法是我國自主設計的公鑰密碼算法,包括SM2-1橢圓曲線數(shù)字簽名算法,SM2-2橢圓曲線密鑰交換協(xié)議,SM2-3橢圓曲線公鑰加密算法,分別用于實現(xiàn)數(shù)字簽名密鑰協(xié)商和數(shù)據加密等功能。SM2算法與RSA算法不同的是,SM2算法是基于橢圓曲線上點群離散對數(shù)難題,相對于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。消息摘要??梢杂肕D5作為對比理解。該算法已公開。校驗結果為256位。
<?php
require_once '../vendor/autoload.php';
use Rtgm\sm\RtSm3;
$sm3 = new RtSm3();
$data = '我愛你ILOVEYOU!';
print_r($sm3->digest($data,1));
SM3HMAC算法PHP實現(xiàn):
// 需要實現(xiàn)hamc-sm3國密定制算法
// composer require axios/tools
// @see https://github.com/AxiosLeo/php-tools/tree/cd576f058db7b633750d62bb6d7d1840f0ab8d5e
$hmac = new HMac();
$hmac->registerAlgorithm('sm3', function ($str) {
// SM3簽名函數(shù)
$sm3 = new SM3();
$sm3->encode($str);
return $sm3->getHex();
});
$s_crypto= $hmac->count('sm3', $s_return, $this->Prvkey);
SM4算法:對稱加密:
可以理解為國產AES。無線局域網標準的分組數(shù)據算法。對稱加密,密鑰長度和分組長度均為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 社區(qū) (learnku.com)
lpilp/phpsm2sm3sm4: php版本,支持國密SM2的簽名算法,非對稱加解密,SM3的hash, SM4的對稱加解密 (github.com)