测试例子

实现完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();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106

算法功能部分实现

将前面几篇的算法实现描述放在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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133

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( sH2.compare(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( u.compare(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++实现:算法功能与测试例子相关推荐

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

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  2. 国密SM9算法C++实现之一:算法简介

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  3. 国密SM9算法C++实现之八:密钥交换算法

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  4. 国密SM9算法C++实现之七:加密解密算法

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  5. 国密SM9算法C++实现之五:签名验签算法

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

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

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  7. 国密SM9算法C++实现之三:椭圆曲线接口、参数初始化

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  8. 国密SM9算法C++实现之四:基本功能函数与KGC接口的实现

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  9. 国密SM3密码杂凑算法原理及实现(附源码)

    相关文章: 国密SM3哈希算法原理及实现(附源码) SHA1哈希算法原理及实现(附源码) MD5哈希算法原理及实现(附源码) MD4哈希算法原理及实现(附源码) MD2哈希算法原理及实现(附源码) M ...

最新文章

  1. 计算机科学与技术专业综合二,计算机科学与技术专业综合一第二页
  2. 特斯拉撞了警车:辅助系统Autopilot全程开启,连撞两车还没自动停下
  3. python 机器移植
  4. 业余学python数据挖掘怎么赚钱_0基础转行学Python,学到什么地步能拿到月薪15k+?...
  5. 网易云信亮相LiveVideoStackCon 2019,解读移动端播放器优化实践
  6. spring boot 集成mybatis连接oracle数据库
  7. Camera Vision - video surveillance on C#
  8. 关于linux的进程和线程
  9. WinXP无需激活的秘技
  10. linux下Makefile学习--注释很好
  11. $bzoj1046-HAOI2007$ 上升子序列 $dp$ 贪心
  12. 基于stc15f2k60s2芯片单片机编程(计算器,不完美)
  13. 在线作图|2分钟做Lefse分析
  14. 职场社交赛道上,脉脉靠什么弯道超车
  15. php 错误 异常,PHP错误异常处理
  16. android下拉框代码,Android下拉列表spinner的实例代码
  17. 网页报503 service unavailable错误怎么解决
  18. Go语言教程第十六集 GORM详解
  19. 浪潮之巅第十三章 — 高科技公司的摇篮:斯坦福大学
  20. 愿我们在路上聪明绝顶但不绝顶

热门文章

  1. 扩散模型(Diffusion Models)
  2. 【概率论与数理统计】第三章知识点复习与习题
  3. 【预告】千亿数据的潘多拉魔盒:从分库分表到分布式数据库
  4. telnet测试http
  5. 苹果已在EEC数据库注册7款笔记本 可能是12英寸和16英寸产品
  6. 一页纸搞定项目管理及操作步骤(文末附可编辑模板)PMP项目管理可用
  7. c语言队列渡船问题,渡船有关问题
  8. 管理类联考笔试还是计算机考,管理类联考笔试究竟难在哪儿?
  9. 无需洪荒之力,轻松搞定奥运会奖牌榜
  10. 硬盘计算机类比推理,2019年国家公务员考试每日一练:类比推理(15)