失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 国密SM9算法C++实现:算法功能与测试例子

国密SM9算法C++实现:算法功能与测试例子

时间:2023-11-24 04:23:31

相关推荐

国密SM9算法C++实现:算法功能与测试例子

测试例子

实现完KGC密钥生成和各个算法功能部分后,可以测试一下。

使用SM9算法时只需要包含KGC.h和SM9.h两个文件,上层数据都用std::string储存,不涉及到底层数据结构。

#include "yy/utils/YHex.h"#include "yy/sm9/SM9.h"#include "yy/sm9/KGC.h"void test() {try {bool initOK = SM9::init(); // or KGC::init();if( !initOK ) {AfxMessageBox(_T("init sm9 parameters failed"));} else{// Test sign and verifyMasterKeyPair signMasterKey = KGC::genSignMasterKeyPair();string signMasterPrikeyHex = YY::YHex::bin2hex(signMasterKey.getPrivate());string signMasterPubkeyHex = YY::YHex::bin2hex(signMasterKey.getPublic());string id = "Alice";string prikey = KGC::genPrivateKey(signMasterKey.getPrivate(), id, KGC::TYPE_PRIVATEKEY::TYPE_SIGN);string prikeyHex = YY::YHex::bin2Hex(prikey);string dataSign = "Chinese IBS standard";Signature signature = SM9::sign(signMasterKey.getPublic(), prikey, dataSign);string signatureHHex = YY::YHex::bin2Hex(signature.getH());string signatureSHex = YY::YHex::bin2Hex(signature.getS());bool isVerifyOK = SM9::verify(signMasterKey.getPublic(), id, signature, dataSign);if( !isVerifyOK ) {AfxMessageBox(_T("Verify signature failed."));}// Test key encap and decap, encrypt and decryptstring dataEncrypt = "Chinese IBE standard";MasterKeyPair encryptMasterKeyPair = KGC::genEncryptMasterKeyPair();string encryptMasterPrikeyHex = YY::YHex::bin2hex(encryptMasterKeyPair.getPrivate());string encryptMasterPubkeyHex = YY::YHex::bin2hex(encryptMasterKeyPair.getPublic());string idKeyEncap = "Bob";int klen = 32;KeyEncapsulation keyEncapsulation = SM9::keyEncap(encryptMasterKeyPair.getPublic(), idKeyEncap, klen);string keyEncapsulationKHex = YY::YHex::bin2Hex(keyEncapsulation.getK());string keyEncapsulationCHex = YY::YHex::bin2Hex(keyEncapsulation.getC());string encryptPrikey = KGC::genPrivateKey(encryptMasterKeyPair.getPrivate(), idKeyEncap, KGC::TYPE_PRIVATEKEY::TYPE_ENCRYPT);string encryptPrikeyHex = YY::YHex::bin2Hex(encryptPrikey);string sK = SM9::keyDecap(encryptPrikey, keyEncapsulation.getC(), idKeyEncap, klen);string skHex = YY::YHex::bin2Hex(sK);bool isBaseBlockCipher = true;Cipher cipher1 = SM9::encrypt(encryptMasterKeyPair.getPublic(), idKeyEncap, dataEncrypt, isBaseBlockCipher, klen);string cipher1Hex = YY::YHex::bin2Hex(cipher1.toByteArray());string plain1 = SM9::decrypt(cipher1, encryptPrikey, idKeyEncap, isBaseBlockCipher, klen);string plain1Hex = YY::YHex::bin2Hex(plain1);isBaseBlockCipher = false;Cipher cipher2 = SM9::encrypt(encryptMasterKeyPair.getPublic(), idKeyEncap, dataEncrypt, isBaseBlockCipher, klen);string cipher2Hex = YY::YHex::bin2Hex(cipher2.toByteArray());string plain2 = SM9::decrypt(cipher2, encryptPrikey, idKeyEncap, isBaseBlockCipher, klen);string plain2Hex = YY::YHex::bin2Hex(plain2);// Test key exchangestring idA = "Alice";string idB = "Bob";klen = 16;MasterKeyPair keyExchangeMasterKeyPair = KGC::genKeyExchangeMasterKeyPair();string keyExchangeMasterPrikeyHex = YY::YHex::bin2hex(keyExchangeMasterKeyPair.getPrivate());string keyExchangeMasterPubkeyHex = YY::YHex::bin2hex(keyExchangeMasterKeyPair.getPublic());string prikeyA= KGC::genPrivateKey(keyExchangeMasterKeyPair.getPrivate(), idA, KGC::TYPE_PRIVATEKEY::TYPE_KEYEXCHANGE);string prikeyAHex= YY::YHex::bin2Hex(prikeyA );string prikeyB = KGC::genPrivateKey(keyExchangeMasterKeyPair.getPrivate(), idB, KGC::TYPE_PRIVATEKEY::TYPE_KEYEXCHANGE);string prikeyBHex = YY::YHex::bin2Hex(prikeyB);TempKeyPair tempKeyPairA = SM9::keyExchange_init(keyExchangeMasterKeyPair.getPublic(), idB);TempKeyPair tempKeyPairB = SM9::keyExchange_init(keyExchangeMasterKeyPair.getPublic(), idA);string tempPubkeyAHex = YY::YHex::bin2Hex(tempKeyPairA.getPublic());string tempPrikeyAHex= YY::YHex::bin2Hex(tempKeyPairA.getPrivate());string tempPubkeyBHex = YY::YHex::bin2Hex(tempKeyPairB.getPublic());string tempPrikeyBHex = YY::YHex::bin2Hex(tempKeyPairB.getPrivate());KeyAgreement keyAgreementB = SM9::keyExchange(keyExchangeMasterKeyPair.getPublic(), false, idB, idA, prikeyB, tempKeyPairB, tempKeyPairA.getPublic(), klen);string SBHex = YY::YHex::bin2Hex(keyAgreementB.getHashB1());string S2Hex = YY::YHex::bin2Hex(keyAgreementB.getHashA2());string sharekeyB = YY::YHex::bin2Hex(keyAgreementB.getShareKey());KeyAgreement keyAgreementA = SM9::keyExchange(keyExchangeMasterKeyPair.getPublic(), true, idA, idB, prikeyA, tempKeyPairA, tempKeyPairB.getPublic(), klen);string S1Hex = YY::YHex::bin2Hex(keyAgreementA.getHashB1());string SAHex = YY::YHex::bin2Hex(keyAgreementA.getHashA2());string sharekeyA = YY::YHex::bin2Hex(keyAgreementA.getShareKey());if( S1Hex == SBHex && S2Hex == SAHex ) {AfxMessageBox(_T("key exchange success."));} else {AfxMessageBox(_T("key exchange failed."));}}} catch( std::exception& e ) {AfxMessageBox(e.what());}SM9::release(); // or KGC::release();}

12345678910111213141516171819222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106

算法功能部分实现

将前面几篇的算法实现描述放在SM9算法实现的算法功能部分的类SM9中。

SM9.h

#ifndef YY_SM9_SM9_INCLUDE_H__#define YY_SM9_SM9_INCLUDE_H__#pragma once#include <string>#include <exception>#include "Base.h"#include "MasterKeyPair.h"#include "Cipher.h"#include "Signature.h"#include "KeyAgreement.h"#include "KeyEncapsulation.h"using namespace std;/** * SM9算法功能部分,包括签名验签算法、密钥封装解封算法、加密解密算法、密钥交换算法.* @author YaoYuan*/class SM9 : public Base {private:SM9();~SM9();public:/** * 签名* * @param masterPublicKey 签名主公钥* @param prikey 用户签名私钥* @param data 待签数据* @return 签名值* @throw std::exception SM9_ERROR_NOT_INIT | SM9_ERROR_CALC_RATE*/static Signature sign(const string& masterPublicKey, const string& prikey, const string& data);/*** 验签** @param masterPublicKey 签名主公钥* @param prikey 用户ID* @param signature 签名值* @param data 待签数据* @return true-验签成功;false-验签失败* @throw std::exception SM9_ERROR_NOT_INIT | SM9_ERROR_CALC_RATE | * SM9_ERROR_VERIFY_H_OUTRANGE | SM9_ERROR_VERIFY_S_NOT_ON_G1 | SM9_ERROR_VERIFY_H_VERIFY_FAILED*/static bool verify(const string& masterPublicKey, const string& id, const Signature& signature, const string& data);/*** 密钥封装** @param masterPublicKey 加密主公钥* @param prikey 用户ID* @param klen 密钥字节长度* @return 密钥封装值* @throw std::exception SM9_ERROR_NOT_INIT | SM9_ERROR_CALC_RATE*/static KeyEncapsulation keyEncap(const string& masterPublicKey, const string& id, int klen);/*** 密钥解封** @param prikey 用户加密私钥* @param C 密钥封装值中的C* @param prikey 用户ID* @param klen 密钥字节长度* @return 密钥* @throw std::exception SM9_ERROR_NOT_INIT | SM9_ERROR_CALC_RATE | SM9_ERROR_DECAP_C_NOT_ON_G1 | SM9_ERROR_DECAP_K_IS_ZERO*/static string keyDecap(const string& prikey, const string& C, const string& id, int klen);/*** 加密** @param masterPublicKey 加密主公钥* @param id 用户ID* @param data 待加密数据* @param isBaseBlockCipher 指明加密明文的方法:true-分组密码;false-基于KDF的序列密码* @param macKeyLen MAC函数的密钥字节长度,应不少于MAC函数中杂凑函数的杂凑值长度。此处可设置32字节* @return 加密值* @throw std::exception SM9_ERROR_NOT_INIT | SM9_ERROR_CALC_RATE*/static Cipher encrypt(const string& masterPublicKey, const string& id, const string& data, bool isBaseBlockCipher, int macKeyLen);/*** 解密** @param cipher 加密值* @param prikey 用户私钥* @param id 用户ID* @param isBaseBlockCipher 指明加密明文的方法:true-分组密码;false-基于KDF的序列密码* @param macKeyLen MAC函数的密钥字节长度,应不少于MAC函数中杂凑函数的杂凑值长度。此处可设置32字节* @return 原始数据* @throw std::exception SM9_ERROR_NOT_INIT | SM9_ERROR_CALC_RATE | * SM9_ERROR_DECRYPT_C1_NOT_ON_G1 | SM9_ERROR_DECRYPT_K1_IS_ZERO | SM9_ERROR_DECRYPT_C3_VERIFY_FAILED*/static string decrypt(const Cipher& cipher, const string& prikey, const string& id, bool isBaseBlockCipher, int macKeyLen);/*** 密钥交换步骤1:初始化** @param masterPublicKey 加密主公钥* @param othId 对方ID* @return 临时密钥对* @throw std::exception SM9_ERROR_NOT_INIT*/static TempKeyPair keyExchange_init(const string& masterPublicKey, const string& othId);/*** 密钥交换步骤2:计算共享密钥** @param masterPublicKey 加密主公钥* @param isSponsor true-发起方;false-响应方* @param myId 己方ID* @param othId 对方ID* @param myTempKeyPair 己方临时密钥对* @param othTempPubkey 对方临时公钥* @param klen 要计算的共享密钥字节长度* @return 密钥交换值* @throw std::exception SM9_ERROR_NOT_INIT | SM9_ERROR_CALC_RATE | SM9_ERROR_KEYEXCHANGE_R_NOT_ON_G1*/static KeyAgreement keyExchange(const string& masterPublicKey, bool isSponsor, const string& myId, const string& othId, const string& myPrikey, const TempKeyPair& myTempKeyPair, const string& othTempPubkey, int klen);};#endif

1234567891011121314151617181922232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811911122123124125126127128129130131132133

SM9.cpp

#include "SM9.h"#include "Errors.h"#include "Parameters.h"#include "KGC.h"#include "zzn12.h"#include "yy/crypto/symmetric/provider/YCipher.h"#include "yy/hash/sm3/YSM3.h"#ifdef SELF_CHECK#include "yy/utils/YHex.h"#endifSM9::SM9(){}SM9::~SM9(){}Signature SM9::sign(const string& masterPublicKey, const string& prikey, const string& data){Signature signature;bool hasException = true;string h, s, sw;ecn2 Ppubs;epoint* dsa = NULL;epoint* S = NULL;ZZN12 g;ZZN12 w;big h2 = NULL;big r = NULL;big l = NULL;big tmp = NULL;big zero = NULL;#ifdef SELF_CHECKstring gHex, rHex, wHex, h2Hex;#endifif( !mIsInit ) {mErrorNum = SM9_ERROR_NOT_INIT;throw exception(getErrorMsg().c_str());}Parameters::init_ecn2(Ppubs);Parameters::init_big(h2);Parameters::init_big(r);Parameters::init_big(l);Parameters::init_big(tmp);Parameters::init_big(zero);Parameters::init_epoint(dsa);Parameters::init_epoint(S);// Step1 : g = e(P1, Ppub-s)Parameters::cin_ecn2_byte128(Ppubs, masterPublicKey.c_str());if( !ZZN12::calcRatePairing(g, Ppubs, Parameters::param_P1, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}#ifdef SELF_CHECKgHex = YY::YHex::bin2Hex(g.toByteArray());#endifwhile( true ) {#ifdef SELF_CHECKrHex = YY::YHex::hex2bin("033C8616B06704813203DFD00965022ED15975C662337AED648835DC4B1CBE");Parameters::cin_big(r, rHex.c_str(), rHex.length());#else// Step2: generate rbigrand(Parameters::param_N, r);#endif// Step3 : calculate w=g^rw = g.pow(r);sw = w.toByteArray();#ifdef SELF_CHECKwHex = YY::YHex::bin2Hex(sw);#endif// Step4 : calculate h=H2(M||w,N)h = KGC::H2(data, sw);Parameters::cin_big(h2, h.c_str(), h.length());#ifdef SELF_CHECKh2Hex = YY::YHex::bin2Hex(h);#endif// Step5 : l=(r-h)mod Nsubtract(r, h2, l);divide(l, Parameters::param_N, tmp);while( mr_compare(l, zero) < 0 )add(l, Parameters::param_N, l);if( mr_compare(l, zero) != 0 )break;}// Step6 : S=[l]dSA=(xS,yS)Parameters::cin_epoint(dsa, prikey.c_str());ecurve_mult(l, dsa, S);s = Parameters::cout_epoint(S);// Step7 : signature=(h,s)signature = Signature(h, s);hasException = false;END:Parameters::release_epoint(dsa);Parameters::release_epoint(S);Parameters::release_ecn2(Ppubs);Parameters::release_big(h2);Parameters::release_big(r);Parameters::release_big(l);Parameters::release_big(tmp);Parameters::release_big(zero);if( hasException ) {throw exception(getErrorMsg().c_str());}return signature;}bool SM9::verify(const string& masterPublicKey, const string& id, const Signature& signature, const string& data){bool result = false;bool hasException = true;big NSub1 = NULL;big one = NULL;big h = NULL;epoint* S = NULL;ecn2 Ppubs;ecn2 P;ZZN12 g;ZZN12 t;ZZN12 u;ZZN12 w;big h1 = NULL;string sH1, sH2, sw, sH, sS;if( !mIsInit ) {mErrorNum = SM9_ERROR_NOT_INIT;throw exception(getErrorMsg().c_str());}sH = signature.getH();sS = signature.getS();#ifdef SELF_CHECKstring gHex, rHex, h1Hex, tHex, pHex, uHex, wHex;#endifParameters::init_big(NSub1);Parameters::init_big(one);Parameters::init_big(h);Parameters::init_epoint(S);Parameters::init_ecn2(Ppubs);Parameters::init_ecn2(P);Parameters::init_big(h1);// Step1 : check if h in the range [1, N-1]decr(Parameters::param_N, 1, NSub1);convert(1, one);Parameters::cin_big(h, sH.c_str(), sH.length());if( (mr_compare(h, one) < 0) | (mr_compare(h, NSub1) > 0) ) {mErrorNum = SM9_ERROR_VERIFY_H_OUTRANGE;goto END;}// Step2 : check if S is on G1Parameters::cin_epoint(S, sS.c_str());if( !Parameters::isPointOnG1(S) ) {mErrorNum = SM9_ERROR_VERIFY_S_NOT_ON_G1;goto END;}// Step3 : g = e(P1, Ppub-s)Parameters::cin_ecn2_byte128(Ppubs, masterPublicKey.c_str());if( !ZZN12::calcRatePairing(g, Ppubs, Parameters::param_P1, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}#ifdef SELF_CHECKgHex = YY::YHex::bin2Hex(g.toByteArray());#endif// Step4 : calculate t=g^ht = g.pow(h);#ifdef SELF_CHECKtHex = YY::YHex::bin2Hex(t.toByteArray());#endif// Step5 : calculate h1=H1(IDA||hid,N)sH1 = KGC::H1(id, HID_SIGN);Parameters::cin_big(h1, sH1.c_str(), sH1.length());#ifdef SELF_CHECKh1Hex = YY::YHex::bin2Hex(sH1);#endif// Step6 : P=[h1]P2+Ppubsecn2_copy(&Parameters::param_P2, &P);ecn2_mul(h1, &P);ecn2_add(&Ppubs, &P);#ifdef SELF_CHECKpHex = YY::YHex::bin2Hex(Parameters::cout_ecn2(P));#endif// Step7 : u=e(S,P)if( !ZZN12::calcRatePairing(u, P, S, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}#ifdef SELF_CHECKuHex = YY::YHex::bin2Hex(u.toByteArray());#endif// Step8 : w=u*tw = u.mul(t);sw = w.toByteArray();#ifdef SELF_CHECKwHex = YY::YHex::bin2Hex(sw);#endif// Step9 : h2=H2(M||w,N)sH2 = KGC::H2(data, sw);if( pare(sH) == 0 ) {result = true;} else {mErrorNum = SM9_ERROR_VERIFY_H_VERIFY_FAILED;}hasException = false;END:Parameters::release_big(NSub1);Parameters::release_big(one);Parameters::release_big(h);Parameters::release_epoint(S);Parameters::release_ecn2(Ppubs);Parameters::release_ecn2(P);Parameters::release_big(h1);if( hasException ) {throw exception(getErrorMsg().c_str());}return result;}KeyEncapsulation SM9::keyEncap(const string& masterPublicKey, const string& id, int klen){KeyEncapsulation keyEncapsulation;bool hasException = true;big h1 = NULL;big r = NULL;epoint *Ppube = NULL;epoint *QB = NULL;epoint *C = NULL;ZZN12 g;ZZN12 w;string sC, sW, bufferZ, sK, hashH1;#ifdef SELF_CHECKstring hashH1Hex, QBHex, rHex, CHex, gHex, wHex;#endifif( !mIsInit ) {mErrorNum = SM9_ERROR_NOT_INIT;throw exception(getErrorMsg().c_str());}Parameters::init_big(h1);Parameters::init_epoint(Ppube);Parameters::init_epoint(QB);Parameters::init_epoint(C);Parameters::init_big(r);hashH1 = KGC::H1(id, HID_ENCRYPT);Parameters::cin_big(h1, hashH1.c_str(), hashH1.length());Parameters::cin_epoint(Ppube, masterPublicKey.c_str());#ifdef SELF_CHECKhashH1Hex = YY::YHex::bin2Hex(hashH1);#endif// Step1 : QB=[H1(IDB||hid, N)]P1+Ppub-eecurve_mult(h1, Parameters::param_P1, QB);ecurve_add(Ppube, QB);#ifdef SELF_CHECKQBHex = YY::YHex::bin2hex(Parameters::cout_epoint(QB));#endifwhile( true ) {#ifdef SELF_CHECKrHex = YY::YHex::hex2bin("74015F8489C01EF4270456F9E6475BFB602BDE7F33FD482AB4E3684A6722");Parameters::cin_big(r, rHex.c_str(), rHex.length());#else// Step2: generate rbigrand(Parameters::param_N, r);#endif// Step3 : C=[r]QBecurve_mult(r, QB, C);sC = Parameters::cout_epoint(C);#ifdef SELF_CHECKCHex = YY::YHex::bin2Hex(sC);#endif// Step4 : g=e(Ppub-e, P2)if( !ZZN12::calcRatePairing(g, Parameters::param_P2, Ppube, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}#ifdef SELF_CHECKgHex = YY::YHex::bin2Hex(g.toByteArray());#endif// Step5 : calculate w=g^rw = g.pow(r);sW = w.toByteArray();#ifdef SELF_CHECKwHex = YY::YHex::bin2Hex(sW);#endif// Step6 : K = KDF(C || w || IDB, klen)bufferZ.append(sC);bufferZ.append(sW);bufferZ.append(id);sK = KGC::KDF(bufferZ, klen);if( !isAllZero(sK) )break;}// Step7 : output (K,C)keyEncapsulation = KeyEncapsulation(sK, sC);hasException = false;END:Parameters::release_big(h1);Parameters::release_big(r);Parameters::release_epoint(Ppube);Parameters::release_epoint(QB);Parameters::release_epoint(C);if( hasException ) {throw exception(getErrorMsg().c_str());}return keyEncapsulation;}std::string SM9::keyDecap(const string& prikey, const string& C, const string& id, int klen){bool hasException = true;string sK, sKi, sW, bufferZ;epoint* bC = NULL;ecn2 de;ZZN12 w;#ifdef SELF_CHECKstring wHex;#endifif( !mIsInit ) {mErrorNum = SM9_ERROR_NOT_INIT;throw exception(getErrorMsg().c_str());}Parameters::init_epoint(bC);Parameters::init_ecn2(de);// Step1 : check if C is on G1Parameters::cin_epoint(bC, C.c_str());if( !Parameters::isPointOnG1(bC) ) {mErrorNum = SM9_ERROR_DECAP_C_NOT_ON_G1;goto END;}// Step2 : w=e(c,de)Parameters::cin_ecn2_byte128(de, prikey.c_str());if( !ZZN12::calcRatePairing(w, de, bC, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}sW = w.toByteArray();#ifdef SELF_CHECKwHex = YY::YHex::bin2Hex(sW);#endif// Step3 : K=KDF(C||w||IDB, klen)bufferZ.append(C);bufferZ.append(sW);bufferZ.append(id);sKi = KGC::KDF(bufferZ, klen);if( isAllZero(sKi) ) {mErrorNum = SM9_ERROR_DECAP_K_IS_ZERO;goto END;}// Step4 : output KsK = sKi;hasException = false;END:Parameters::release_epoint(bC);Parameters::release_ecn2(de);if( hasException ) {throw exception(getErrorMsg().c_str());}return sK;}Cipher SM9::encrypt(const string& masterPublicKey, const string& id, const string& data, bool isBaseBlockCipher, int macKeyLen){Cipher cipher;bool hasException = true;big h1 = NULL;big r = NULL;epoint *Ppube = NULL;epoint *QB = NULL;epoint *C1 = NULL;ZZN12 g;ZZN12 w;string sC1, sC2, sC3, sW, bufferZ, sK, sK1, sK2, tmp, hashH1;int klen = 0;int k1len = 16; // key length for sm4int k2len = macKeyLen;#ifdef SELF_CHECKstring hashH1Hex, QBHex, rHex, C1Hex, C2Hex, C3Hex, gHex, wHex, K1Hex, K2Hex;#endifif( !mIsInit ) {mErrorNum = SM9_ERROR_NOT_INIT;throw exception(getErrorMsg().c_str());}Parameters::init_big(h1);Parameters::init_epoint(Ppube);Parameters::init_epoint(QB);Parameters::init_epoint(C1);Parameters::init_big(r);hashH1 = KGC::H1(id, HID_ENCRYPT);Parameters::cin_big(h1, hashH1.c_str(), hashH1.length());Parameters::cin_epoint(Ppube, masterPublicKey.c_str());#ifdef SELF_CHECKhashH1Hex = YY::YHex::bin2Hex(hashH1);#endif// Step1 : QB=[H1(IDB||hid, N)]P1+Ppub-eecurve_mult(h1, Parameters::param_P1, QB);ecurve_add(Ppube, QB);#ifdef SELF_CHECKQBHex = YY::YHex::bin2hex(Parameters::cout_epoint(QB));#endifwhile( true ) {#ifdef SELF_CHECKrHex = YY::YHex::hex2bin("AAC0541779C8FC45E3E2CB25C12B5D2576B2129AE8BB5EE2CBE5EC9E785C");Parameters::cin_big(r, rHex.c_str(), rHex.length());#else// Step2: generate rbigrand(Parameters::param_N, r);#endif// Step3 : C1=[r]QBecurve_mult(r, QB, C1);sC1 = Parameters::cout_epoint(C1);#ifdef SELF_CHECKC1Hex = YY::YHex::bin2Hex(sC1);#endif// Step4 : g=e(Ppub-e, P2)if( !ZZN12::calcRatePairing(g, Parameters::param_P2, Ppube, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}#ifdef SELF_CHECKgHex = YY::YHex::bin2Hex(g.toByteArray());#endif// Step5 : calculate w=g^rw = g.pow(r);sW = w.toByteArray();#ifdef SELF_CHECKwHex = YY::YHex::bin2Hex(sW);#endif// Step6_1 : K = KDF(C1 || w || IDB, klen)if( isBaseBlockCipher ) {klen = k1len + k2len;} else {klen = data.length() + k2len;}bufferZ.append(sC1);bufferZ.append(sW);bufferZ.append(id);sK = KGC::KDF(bufferZ, klen);sK1 = string(sK, 0, sK.length()-k2len);sK2 = string(sK, sK1.length(), sK.length()-sK1.length());#ifdef SELF_CHECKK1Hex = YY::YHex::bin2Hex(sK1);K2Hex = YY::YHex::bin2Hex(sK2);#endifif( !isAllZero(sK1) )break;}// Step6_2if( isBaseBlockCipher ) {// C2=Enc(K1,M)YY::YCipher sm4Cipher = YY::YCipher(YY::YCipher::SM4, YY::YCipher::ECB, YY::YCipher::PKCS5Padding);sm4Cipher.init(YY::YCipher::ENCRYPT, sK1);sC2 = sm4Cipher.update(data);tmp = sm4Cipher.doFinal();sC2.append(tmp);} else {// C2=M^K1for( int i = 0; i < data.length(); i++ ) {sC2.append(1, data[i] ^ sK1[i]);}}// Step7 : C3=MAC(K2,C2)sC3 = MAC(sK2, sC2);#ifdef SELF_CHECKC2Hex = YY::YHex::bin2Hex(sC2);C3Hex = YY::YHex::bin2Hex(sC3);#endif// Step8 : C=C1|C3|C2cipher = Cipher(sC1, sC2, sC3);hasException = false;END:Parameters::release_big(h1);Parameters::release_big(r);Parameters::release_epoint(Ppube);Parameters::release_epoint(QB);Parameters::release_epoint(C1);if( hasException ) {throw exception(getErrorMsg().c_str());}return cipher;}std::string SM9::decrypt(const Cipher& cipher, const string& prikey, const string& id, bool isBaseBlockCipher, int macKeyLen){bool hasException = true;string result, sC1, sC2, sC3, sK1, sK2, sK, sW, bufferZ, tmp, u, M;epoint* C1 = NULL;ecn2 de;ZZN12 w;YY::YSM3 sm3Digest;int klen = 0;int k1len = 16; // key length for sm4int k2len = macKeyLen;#ifdef SELF_CHECKstring wHex, K1Hex, K2Hex, uHex, MHex;#endifif( !mIsInit ) {mErrorNum = SM9_ERROR_NOT_INIT;throw exception(getErrorMsg().c_str());}sC1 = cipher.getC1();sC2 = cipher.getC2();sC3 = cipher.getC3();Parameters::init_epoint(C1);Parameters::init_ecn2(de);// Step1 : check if C1 is on G1Parameters::cin_epoint(C1, sC1.c_str());if( !Parameters::isPointOnG1(C1) ) {mErrorNum = SM9_ERROR_DECRYPT_C1_NOT_ON_G1;goto END;}// Step2 : w=e(c,de)Parameters::cin_ecn2_byte128(de, prikey.c_str());if( !ZZN12::calcRatePairing(w, de, C1, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}sW = w.toByteArray();#ifdef SELF_CHECKwHex = YY::YHex::bin2Hex(sW);#endif// Step3_1 : K = KDF(C1 || w || IDB, klen)if( isBaseBlockCipher ) {klen = k1len + k2len;} else {klen = sC2.length() + k2len;}bufferZ.append(sC1);bufferZ.append(sW);bufferZ.append(id);sK = KGC::KDF(bufferZ, klen);sK1 = string(sK, 0, sK.length() - k2len);sK2 = string(sK, sK1.length(), sK.length() - sK1.length());#ifdef SELF_CHECKK1Hex = YY::YHex::bin2Hex(sK1);K2Hex = YY::YHex::bin2Hex(sK2);#endifif( isAllZero(sK1) ) {mErrorNum = SM9_ERROR_DECRYPT_K1_IS_ZERO;goto END;}// Step3_2if( isBaseBlockCipher ) {// M=Dec(K1,C2)YY::YCipher sm4Cipher = YY::YCipher(YY::YCipher::SM4, YY::YCipher::ECB, YY::YCipher::PKCS5Padding);sm4Cipher.init(YY::YCipher::DECRYPT, sK1);M = sm4Cipher.update(sC2);tmp = sm4Cipher.doFinal();M.append(tmp);} else {// M=C2^K1for( int i = 0; i < sC2.length(); i++ ) {M.append(1, sC2[i] ^ sK1[i]);}}// Step4 : u=MAC(K2,C2)u = MAC(sK2, sC2);if( pare(sC3) != 0 ) {mErrorNum = SM9_ERROR_DECRYPT_C3_VERIFY_FAILED;goto END;}#ifdef SELF_CHECKMHex = YY::YHex::bin2Hex(M);uHex = YY::YHex::bin2Hex(u);#endif// Step5result = M;hasException = false;END:Parameters::release_epoint(C1);Parameters::release_ecn2(de);if( hasException ) {throw exception(getErrorMsg().c_str());}return result;}TempKeyPair SM9::keyExchange_init(const string& masterPublicKey, const string& othId){string sR, sr, hashH1, sg, sg3, sg0, bufferZ;big h1 = NULL;big r = NULL;epoint *Ppube = NULL;epoint *Qoth = NULL;epoint *R = NULL;#ifdef SELF_CHECKstring H1Hex, QothHex, rHex, RHex, gHex, g3Hex, g0Hex;#endifif( !mIsInit ) {mErrorNum = SM9_ERROR_NOT_INIT;throw exception(getErrorMsg().c_str());}Parameters::init_big(h1);Parameters::init_big(r);Parameters::init_epoint(Qoth);Parameters::init_epoint(Ppube);Parameters::init_epoint(R);hashH1 = KGC::H1(othId, HID_KEYEXCHANGE);Parameters::cin_big(h1, hashH1.c_str(), hashH1.length());Parameters::cin_epoint(Ppube, masterPublicKey.c_str());#ifdef SELF_CHECKH1Hex = YY::YHex::bin2Hex(hashH1);#endif// Step1 : QB =[H1(IDB||hid, N)]P1 +Ppub-e or QA = [H1(IDA || hid, N)]P1 + Ppub-eecurve_mult(h1, Parameters::param_P1, Qoth);ecurve_add(Ppube, Qoth);#ifdef SELF_CHECKQothHex = YY::YHex::bin2hex(Parameters::cout_epoint(Qoth));#endif#ifdef SELF_CHECKif( othId=="Bob" )rHex = YY::YHex::hex2bin("5879DD1D51E175946F23B1B41E93BA31C584AE59A426EC1046A4D03B06C8");elserHex = YY::YHex::hex2bin("018B98C44BEF9F8537FB7D071B2C928B3BC65BD3D69E1EEE213564905634FE");Parameters::cin_big(r, rHex.c_str(), rHex.length());#else// Step2: generate rbigrand(Parameters::param_N, r);#endif// Step3 : RA = [rA]QB or RB= [rB]QAecurve_mult(r, Qoth, R);sr = Parameters::cout_big(r);sR = Parameters::cout_epoint(R);Parameters::release_big(h1);Parameters::release_big(r);Parameters::release_epoint(Qoth);Parameters::release_epoint(Ppube);Parameters::release_epoint(R);return TempKeyPair(sr, sR);}KeyAgreement SM9::keyExchange(const string& masterPublicKey, bool isSponsor, const string& myId, const string& othId, const string& myPrikey, const TempKeyPair& myTempKeyPair, const string& othTempPubkey, int klen){KeyAgreement keyAgreement;bool hasException = true;string sKey, sg1, sg2, sg3, bufferZ, bufferTmp, srmy, sRmy, sRoth, SB1, SA2, tmp;epoint *Ppube = NULL;epoint *Qoth = NULL;epoint *Rmy = NULL;epoint *Roth = NULL;big rmy = NULL;ZZN12 g1;ZZN12 g2;ZZN12 g3;ZZN12 gtmp;ecn2 de;YY::YSM3 sm3Digest;#ifdef SELF_CHECKstring g1Hex, g2Hex, g3Hex;#endifif( !mIsInit ) {mErrorNum = SM9_ERROR_NOT_INIT;throw exception(getErrorMsg().c_str());}Parameters::init_epoint(Qoth);Parameters::init_epoint(Ppube);Parameters::init_epoint(Rmy);Parameters::init_epoint(Roth);Parameters::init_big(rmy);Parameters::init_ecn2(de);srmy = myTempKeyPair.getPrivate();sRmy = myTempKeyPair.getPublic();Parameters::cin_big(rmy, srmy.c_str(), srmy.length());Parameters::cin_epoint(Rmy, sRmy.c_str());sRoth = othTempPubkey;Parameters::cin_epoint(Roth, sRoth.c_str());// check R is on G1if( !Parameters::isPointOnG1(Rmy) ) {mErrorNum = SM9_ERROR_KEYEXCHANGE_R_NOT_ON_G1;goto END;}// StepA5_B4: g=e(Ppub-e,P2)^rParameters::cin_epoint(Ppube, masterPublicKey.c_str());if( !ZZN12::calcRatePairing(gtmp, Parameters::param_P2, Ppube, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}if( isSponsor )g1 = gtmp.pow(rmy);elseg2 = gtmp.pow(rmy);// g=e(Roth,de)Parameters::cin_ecn2_byte128(de, myPrikey.c_str());if( !ZZN12::calcRatePairing(gtmp, de, Roth, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}if( isSponsor )g2 = gtmp;elseg1 = gtmp;// g3=g^rif( isSponsor )g3 = g2.pow(rmy);elseg3 = g1.pow(rmy);sg1 = g1.toByteArray();sg2 = g2.toByteArray();sg3 = g3.toByteArray();#ifdef SELF_CHECKg1Hex = YY::YHex::bin2Hex(sg1);g2Hex = YY::YHex::bin2Hex(sg2);g3Hex = YY::YHex::bin2Hex(sg3);#endif// Step6 : S1 or SBbufferTmp.resize(0);if( isSponsor ) {bufferTmp.append(myId);bufferTmp.append(othId);bufferTmp.append(sRmy);bufferTmp.append(sRoth);} else {bufferTmp.append(othId);bufferTmp.append(myId);bufferTmp.append(sRoth);bufferTmp.append(sRmy);}bufferZ.resize(0);bufferZ.append(sg2);bufferZ.append(sg3);bufferZ.append(bufferTmp);sm3Digest.update(bufferZ);sm3Digest.finish();tmp = sm3Digest.getData();bufferZ.resize(0);bufferZ.append(1, (char)0x82);bufferZ.append(sg1);bufferZ.append(tmp);sm3Digest.update(bufferZ);sm3Digest.finish();SB1 = sm3Digest.getData();// StepA8_B7 : SA or S2bufferZ[0] = (char)0x83;sm3Digest.update(bufferZ);sm3Digest.finish();SA2 = sm3Digest.getData();// StepA7_B5 : SKA or SKBbufferZ.resize(0);bufferZ.append(bufferTmp);bufferZ.append(sg1);bufferZ.append(sg2);bufferZ.append(sg3);sKey = KGC::KDF(bufferZ, klen);keyAgreement = KeyAgreement(sKey, SA2, SB1);hasException = false;END:Parameters::release_epoint(Qoth);Parameters::release_epoint(Ppube);Parameters::release_epoint(Rmy);Parameters::release_epoint(Roth);Parameters::release_big(rmy);Parameters::release_ecn2(de);if( hasException ) {throw exception(getErrorMsg().c_str());}return keyAgreement;}

如果觉得《国密SM9算法C++实现:算法功能与测试例子》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。