國密SM2/3/4 PHP


國密即國家密碼局認定的國產密碼算法。主要有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)

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容