首页 > 编程知识 正文

国密SM9算法C 实现之八密钥交换算法

时间:2023-05-03 05:08:20 阅读:179581 作者:4111

SM9算法C++实现系列目录:

基于JPBC的SM9算法的java实现与测试

实现国密SM9算法c的0 :源代码下载地址

国密SM9算法c的实现之一:算法综述

实现国密SM9算法c之二:测试工具

实现国密SM9算法c之三:椭圆曲线界面,参数初始化

国密SM9算法c的实现之四:基本功能函数和KGC接口的实现

国密SM9算法c的实现之五:签名验证算法

国密SM9算法c的实现之六:密钥解封装算法

国密SM9算法c的实现之七:密码破译算法

国密SM9算法c的实现之八:密钥交换算法

国密SM9算法c的实现之九:算法的功能和测试实例

国密SM9算法c实现之八:密钥交换算法文章目录国密SM9算法c实现之八:密钥交换算法@[toc]密钥交换算法进程密钥交换结果值密钥协商初始化: keyExchange_init临时密钥对

流程图如下。

密钥交换结果值SM9密钥交换结果包含两个可选的野性地验证值和一个共享密钥值,这也简单地封装在一个类中。

密钥协商初始化: keyExchange_init根据算法的记述和算法的流程图,在密钥交换的第1步骤~第3部分中,需要生成[1,N-1]的范围内的随机数,计算G1群上的倍点这可以理解为G1群上的公钥对,私钥是随机数,公钥是倍点,生成G1群上的倍点的过程

另外,在A4和B7中,需要将公钥发送到对方。 因此,这里取出前三个步骤,作为密钥交换的初始化部分,该接口命名为keyExchange_init

临时密钥对: TempKeyPair keyExchange_init密钥协商初始化的结果,生成G1上的临时公钥对,封装在TempKeyPair中,并存储在密钥交换结果值中。

ky agreement.h # ifndef YY _ sm9 _ key agreement _ include _ h _ # define YY _ sm9 _ key agreement _ include _ h _ key 包括两个散列认证值和共享密钥。 * @ author yaoyuan */classkeyagreement { public 3360 key agreement (} key agreement ) ) constst mHashA2=hashA2; mHashB1=hashB1; }~key agreement ({ } public : stringgetsharekey ) ) {return mShareKey; (}string getHashA2) ) {return mHashA2; }string getHashB1() {return mHashB1; }private:/**共享密钥. */string mShareKey; /**选项S_A或S_2. */string mHashA2; /**选项S_B或S_1. */string mHashB1; (; /***密钥交换中的临时密钥对是组G1上的公钥对。 * @ author yaoyuan */classtempkeypair { public 3360 temp key pair (} ); TEMPkeypair(conststringprikey,const string pubkey ) : MP rikey (m pubkey ) { } public 3360 string get prikey } string } private :字符串MP rikey; string mPubkey; (; #endif接口说明根据以上说明定义两个接口函数。

/***密钥交换过程** @param masterPublicKey加密主公钥* @param othId对方ID* @return临时密钥对* 初始化@ throws TD 33603360 exceptionsm9_ error _的statictempkeypairkeyexchange _ init (conststringmasterpublickey,const strinst /**密钥交换步骤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);

需要注意的是,密钥交换初始化时使用的对方的ID。
因为密钥交换的发起方和响应方的算法流程是一样的,因此将其封装为一个函数,只是在传入参数是需要区别一下己方和对方。

密钥交换算法实现

按照密钥交换流程,实现密钥交换算法:

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(Roth) ) {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;}

总结算法实现,实际的密钥交换流程为:

首先发起方需要知道响应方的ID,然后发起方用响应方的ID调用keyExchange_init,生成一对临时密钥对,并将其中的公钥和自己的ID告知响应方。响应方用发起方的ID调用keyExchange_init,生成一对临时密钥对。响应方用发起方的临时公钥、发起方的ID和自己的参数调用keyExchange,计算出野性的大侠选项和共享密钥。然后响应方将自己的临时公钥和野性的大侠选项告知发起方。发起方用响应方的临时公钥和自己的参数调用keyExchange,计算出野性的大侠选项和共享密钥。然后和响应方的野性的大侠选项进行对比,以决定成败与否。当然,双方的野性的大侠选项的验证可以按照SM9标准文档的描述进行。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。