国密SM9算法C++实现之六:密钥封装解封算法

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]
    • 密钥封装算法流程
      • 密钥封装值
      • 密钥封装算法实现
    • 密钥解封算法流程
      • 密钥解封算法实现

密钥封装算法流程

SM9标准文档中描述的密钥封装算法流程如下所示:
国密SM9算法C++实现之六:密钥封装解封算法_第1张图片

其流程图为:
国密SM9算法C++实现之六:密钥封装解封算法_第2张图片

根据算法描述,定义接口函数:

	/**
	* 密钥封装
	*
	* @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);

密钥封装值

SM9密钥封装结果包括密钥本身K和密钥密文C两个部分,对此,也简单将其封装为一个类。


#ifndef YY_SM9_KEYENCAP_INCLUDE_H__
#define YY_SM9_KEYENCAP_INCLUDE_H__

#pragma once

#include 

using namespace std;

/**
* 密钥封装结果值类,包括密钥K和封装值C.
* @author YaoYuan
*/
class KeyEncapsulation {
public:
	KeyEncapsulation() {}
	KeyEncapsulation(const string& k, const string& c) {
		mK = k;
		mC = c;
	}
	~KeyEncapsulation() {}

public:
	string getK() const { return mK; }
	string getC() const { return mC; }

private:
	string mK;
	string mC;
};


#endif

密钥封装算法实现

按照密钥封装流程,实现密钥封装算法:


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_CHECK
	string hashH1Hex, QBHex, rHex, CHex, gHex, wHex;
#endif

	if( !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_CHECK
	hashH1Hex = YY::YHex::bin2Hex(hashH1);
#endif

	// Step1 : QB=[H1(IDB||hid, N)]P1+Ppub-e
	ecurve_mult(h1, Parameters::param_P1, QB);
	ecurve_add(Ppube, QB);

#ifdef SELF_CHECK
	QBHex = YY::YHex::bin2hex(Parameters::cout_epoint(QB));
#endif

	while( true ) {
#ifdef SELF_CHECK
		rHex = YY::YHex::hex2bin("74015F8489C01EF4270456F9E6475BFB602BDE7F33FD482AB4E3684A6722");
		Parameters::cin_big(r, rHex.c_str(), rHex.length());
#else
	// Step2: generate r
		bigrand(Parameters::param_N, r);
#endif

	// Step3 : C=[r]QB
		ecurve_mult(r, QB, C);
		sC = Parameters::cout_epoint(C);

#ifdef SELF_CHECK
		CHex = 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_CHECK
		gHex = YY::YHex::bin2Hex(g.toByteArray());
#endif

	// Step5 : calculate w=g^r
		w = g.pow(r);
		sW = w.toByteArray();

#ifdef SELF_CHECK
		wHex = 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;
}

密钥解封算法流程

SM9标准文档中描述的密钥解封算法流程如下所示:
国密SM9算法C++实现之六:密钥封装解封算法_第3张图片

其流程为:
国密SM9算法C++实现之六:密钥封装解封算法_第4张图片

根据算法描述,定义接口函数:

	/**
	* 密钥解封
	*
	* @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);

需要注意的是,密钥解封时的密钥长度应该和密钥封装时的一致。

密钥解封算法实现


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_CHECK
	string wHex;
#endif

	if( !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 G1
	Parameters::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_CHECK
	wHex = 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 K
	sK = sKi;
	hasException = false;
END:
	Parameters::release_epoint(bC);
	Parameters::release_ecn2(de);

	if( hasException ) {
		throw exception(getErrorMsg().c_str());
	}
	return sK;
}

你可能感兴趣的:(程序设计)