博客
关于我
SM9-加解密
阅读量:708 次
发布时间:2019-03-17

本文共 15550 字,大约阅读时间需要 51 分钟。

算法过程

           

             

程序实现

///************************************************************************ //  File name:    SM9_enc_dec.c //  Version:      SM9_enc_dec_V1.0 //  Date:         Dec 29,2016 //  Description:  implementation of SM9 encryption algorithm and decryption algorithm //                all operations based on BN curve line function //  Function List: //        1.bytes128_to_ecn2        //convert 128 bytes into ecn2 //        2.zzn12_ElementPrint      //print all element of struct zzn12 //        3.ecn2_Bytes128_Print     //print 128 bytes of ecn2 //        4.LinkCharZzn12           //link two different types(unsigned char and zzn12)to one(unsigned char) //        5.Test_Point              //test if the given point is on SM9 curve //        6.SM4_Block_Encrypt       //encrypt the message with padding,according to PKS#5 //        7.SM4_Block_Decrypt       //decrypt the cipher with padding,according to PKS#5 //        8.SM9_H1                  //function H1 in SM9 standard 5.4.2.2 //        9.SM9_Enc_MAC             //MAC in SM9 standard 5.4.5 //        10.SM9_Init               //initiate SM9 curve //        11.SM9_GenerateEncryptKey //generate encrypted private and public key //        12.SM9_Encrypt            //SM9 encryption algorithm //        13.SM9_Decrypt            //SM9 decryption algorithm //        14.SM9_SelfCheck()        //SM9 slef-check // // Notes: // This SM9 implementation source code can be used for academic, non-profit making or non-commercial use only. // This SM9 implementation is created on MIRACL. SM9 implementation source code provider does not provide MIRACL library, MIRACL license or any permission to use MIRACL library. Any commercial use of MIRACL requires a license which may be obtained from Shamus Software Ltd. //**************************************************************************/ #include "SM9_enc_dec.h" #include "kdf.h" #include "SM4.h" /****************************************************************Function:       bytes128_to_ecn2Description:    convert 128 bytes into ecn2Calls:          MIRACL functionsCalled By:      SM9_Init,SM9_DecryptInput:          Ppubs[]Output:         ecn2 *resReturn:         FALSE: execution errorTRUE: execute correctlyOthers:****************************************************************/BOOL bytes128_to_ecn2(unsigned char Ppubs[], ecn2 *res){	zzn2 x, y;	big a, b;	ecn2 r;	r.x.a = mirvar(0); r.x.b = mirvar(0);	r.y.a = mirvar(0); r.y.b = mirvar(0);	r.z.a = mirvar(0); r.z.b = mirvar(0);	r.marker = MR_EPOINT_INFINITY;	x.a = mirvar(0); x.b = mirvar(0);	y.a = mirvar(0); y.b = mirvar(0);	a = mirvar(0); b = mirvar(0);	bytes_to_big(BNLEN, Ppubs, b);	bytes_to_big(BNLEN, Ppubs + BNLEN, a);	zzn2_from_bigs(a, b, &x);	bytes_to_big(BNLEN, Ppubs + BNLEN * 2, b);	bytes_to_big(BNLEN, Ppubs + BNLEN * 3, a);	zzn2_from_bigs(a, b, &y);	return ecn2_set(&x, &y, res);}/****************************************************************Function:       zzn12_ElementPrintDescription:    print all element of struct zzn12Calls:          MIRACL functionsCalled By:      SM9_Encrypt,SM9_DecryptInput:          zzn12 xOutput:         NULLReturn:         NULLOthers:****************************************************************/void zzn12_ElementPrint(zzn12 x){	big tmp;	tmp = mirvar(0);	redc(x.c.b.b, tmp); cotnum(tmp, stdout);	redc(x.c.b.a, tmp); cotnum(tmp, stdout);	redc(x.c.a.b, tmp); cotnum(tmp, stdout);	redc(x.c.a.a, tmp); cotnum(tmp, stdout);	redc(x.b.b.b, tmp); cotnum(tmp, stdout);	redc(x.b.b.a, tmp); cotnum(tmp, stdout);	redc(x.b.a.b, tmp); cotnum(tmp, stdout);	redc(x.b.a.a, tmp); cotnum(tmp, stdout);	redc(x.a.b.b, tmp); cotnum(tmp, stdout);	redc(x.a.b.a, tmp); cotnum(tmp, stdout);	redc(x.a.a.b, tmp); cotnum(tmp, stdout);	redc(x.a.a.a, tmp); cotnum(tmp, stdout);}/****************************************************************Function:       ecn2_Bytes128_PrintDescription:    print 128 bytes of ecn2Calls:          MIRACL functionsCalled By:      SM9_Encrypt,SM9_DecryptInput:          ecn2 xOutput:         NULLReturn:         NULLOthers:****************************************************************/void ecn2_Bytes128_Print(ecn2 x){	big tmp;	tmp = mirvar(0);	redc(x.x.b, tmp); cotnum(tmp, stdout);	redc(x.x.a, tmp); cotnum(tmp, stdout);	redc(x.y.b, tmp); cotnum(tmp, stdout);	redc(x.y.a, tmp); cotnum(tmp, stdout);}/****************************************************************Function:       LinkCharZzn12Description:    link two different types(unsigned char and zzn12)to one(unsigned char)Calls:          MIRACL functionsCalled By:      SM9_Encrypt,SM9_DecryptInput:          message:len:    length of messagew:      zzn12 elementOutput:         Z:      the characters array stored message and wZlen:   length of ZReturn:         NULLOthers:****************************************************************/void LinkCharZzn12(unsigned char *message, int len, zzn12 w, unsigned char *Z, int Zlen){	big tmp;	tmp = mirvar(0);	memcpy(Z, message, len);	redc(w.c.b.b, tmp); big_to_bytes(BNLEN, tmp, Z + len, 1);	redc(w.c.b.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN, 1);	redc(w.c.a.b, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 2, 1);	redc(w.c.a.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 3, 1);	redc(w.b.b.b, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 4, 1);	redc(w.b.b.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 5, 1);	redc(w.b.a.b, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 6, 1);	redc(w.b.a.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 7, 1);	redc(w.a.b.b, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 8, 1);	redc(w.a.b.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 9, 1);	redc(w.a.a.b, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 10, 1);	redc(w.a.a.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 11, 1);}/****************************************************************Function:       Test_PointDescription:    test if the given point is on SM9 curveCalls:Called By:      SM9_DecryptInput:          pointOutput:         nullReturn:         0: success1: not a valid point on curveOthers:****************************************************************/int Test_Point(epoint* point){	big x, y, x_3, tmp;	epoint *buf;	x = mirvar(0); y = mirvar(0);	x_3 = mirvar(0);	tmp = mirvar(0);	buf = epoint_init();	//test if y^2=x^3+b 	epoint_get(point, x, y);	power(x, 3, para_q, x_3);     //x_3=x^3 mod p 	multiply(x, para_a, x);	divide(x, para_q, tmp);	add(x_3, x, x);                  //x=x^3+ax+b 	add(x, para_b, x);	divide(x, para_q, tmp);          //x=x^3+ax+b mod p 	power(y, 2, para_q, y);        //y=y^2 mod p 	if (mr_compare(x, y) != 0)		return 1;	//test infinity 	ecurve_mult(N, point, buf);	if (point_at_infinity(buf) == FALSE)		return 1;	return 0;}/***************************************************************Function:       SM4_Block_EncryptDescription:    encrypt the message with padding,according to PKS#5Calls:          SM4_EncryptCalled By:      SM9_EncryptInput:key:the key of SM4message:data to be encryptedmlen:   the length of messageOutput:cipher: ciphertextcipher_len:the length of ciphertextReturn:         NULLOthers:****************************************************************/void SM4_Block_Encrypt(unsigned char key[], unsigned char * message, int mlen, unsigned char *cipher, int * cipher_len){	unsigned char mess[16];	int i, rem = mlen % 16;	for (i = 0; i
= 0; i--)//key[从大到小] { premult(i256, ha[i], tmp); add(hh, tmp, hh); premult(i256, 256, i256); divide(i256, n1, tmp); divide(hh, n1, tmp); } incr(hh, 1, h1); free(ZH); free(ha); return 0;}/****************************************************************Function: SM9_Enc_MACDescription: MAC in SM9 standard 5.4.5Calls: SM3_256Called By: SM9_Encrypt,SM9_DecryptInput:K:keyKlen:the length of KM:messageMlen:the length of messageOutput: C=MAC(K,Z)Return: 0: success;1: asking for memory errorOthers:****************************************************************/int SM9_Enc_MAC(unsigned char *K, int Klen, unsigned char *M, int Mlen, unsigned char C[]){ unsigned char *Z = NULL; int len = Klen + Mlen; Z = (char *)malloc(sizeof(char)*(len + 1)); if (Z == NULL) return SM9_ASK_MEMORY_ERR; memcpy(Z, M, Mlen); memcpy(Z + Mlen, K, Klen); SM3_256(Z, len, C); free(Z); return 0;}/****************************************************************Function: SM9_InitDescription: Initiate SM9 curveCalls: MIRACL functionsCalled By: SM9_SelfCheckInput: nullOutput: nullReturn: 0: success;5: base point P1 error6: base point P2 errorOthers:****************************************************************/int SM9_Init(){ big P1_x, P1_y; mip = mirsys(1000, 16);; mip->IOBASE = 16; para_q = mirvar(0); N = mirvar(0); P1_x = mirvar(0); P1_y = mirvar(0); para_a = mirvar(0); para_b = mirvar(0); para_t = mirvar(0); X.a = mirvar(0); X.b = mirvar(0); P2.x.a = mirvar(0); P2.x.b = mirvar(0); P2.y.a = mirvar(0); P2.y.b = mirvar(0); P2.z.a = mirvar(0); P2.z.b = mirvar(0); P2.marker = MR_EPOINT_INFINITY; P1 = epoint_init(); bytes_to_big(BNLEN, SM9_q, para_q); bytes_to_big(BNLEN, SM9_P1x, P1_x); bytes_to_big(BNLEN, SM9_P1y, P1_y); bytes_to_big(BNLEN, SM9_a, para_a); bytes_to_big(BNLEN, SM9_b, para_b); bytes_to_big(BNLEN, SM9_N, N); bytes_to_big(BNLEN, SM9_t, para_t); mip->TWIST = MR_SEXTIC_M; ecurve_init(para_a, para_b, para_q, MR_PROJECTIVE); //Initialises GF(q) elliptic curve //MR_PROJECTIVE specifying projective coordinates if (!epoint_set(P1_x, P1_y, 0, P1)) return SM9_G1BASEPOINT_SET_ERR; if (!(bytes128_to_ecn2(SM9_P2, &P2))) return SM9_G2BASEPOINT_SET_ERR; set_frobenius_constant(&X); return 0;}/***************************************************************Function: SM9_GenerateEncryptKeyDescription: Generate encryption keys(public key and private key)Calls: MIRACL functions,SM9_H1,xgcd,ecn2_Bytes128_PrintCalled By: SM9_SelfCheckInput: hid:0x03ID:identificationIDlen:the length of IDke:master private key used to generate encryption public key and private keyOutput: Ppubs:encryption public keydeB: encryption private keyReturn: 0: success;1: asking for memory errorOthers:****************************************************************/int SM9_GenerateEncryptKey(unsigned char hid[], unsigned char *ID, int IDlen, big ke, unsigned char Ppubs[], unsigned char deB[]){ big h1, t1, t2, rem, xPpub, yPpub, tmp; unsigned char *Z = NULL; int Zlen = IDlen + 1, buf; ecn2 dEB; epoint *Ppub; h1 = mirvar(0); t1 = mirvar(0); t2 = mirvar(0); rem = mirvar(0); tmp = mirvar(0); xPpub = mirvar(0); yPpub = mirvar(0); Ppub = epoint_init(); dEB.x.a = mirvar(0); dEB.x.b = mirvar(0); dEB.y.a = mirvar(0); dEB.y.b = mirvar(0); dEB.z.a = mirvar(0); dEB.z.b = mirvar(0); dEB.marker = MR_EPOINT_INFINITY; Z = (char *)malloc(sizeof(char)*(Zlen + 1)); memcpy(Z, ID, IDlen); memcpy(Z + IDlen, hid, 1); buf = SM9_H1(Z, Zlen, N, h1); if (buf != 0) return buf; add(h1, ke, t1);//t1=H1(IDA||hid,N)+ks xgcd(t1, N, t1, t1, t1);//t1=t1(-1) multiply(ke, t1, t2); divide(t2, N, rem);//t2=ks*t1(-1) //Ppub=[ke]P2 ecurve_mult(ke, P1, Ppub); //deB=[t2]P2 ecn2_copy(&P2, &dEB); ecn2_mul(t2, &dEB); printf("\n**************用户B私钥 deB = (xdeB, ydeB):*********************\n"); ecn2_Bytes128_Print(dEB); printf("\n*******************加密主公钥 Ppubs=[ke]P1:**********************\n"); epoint_get(Ppub, xPpub, yPpub); cotnum(xPpub, stdout); cotnum(yPpub, stdout); epoint_get(Ppub, xPpub, yPpub); big_to_bytes(BNLEN, xPpub, Ppubs, 1); big_to_bytes(BNLEN, yPpub, Ppubs + BNLEN, 1); redc(dEB.x.b, tmp); big_to_bytes(BNLEN, tmp, deB, 1); redc(dEB.x.a, tmp); big_to_bytes(BNLEN, tmp, deB + BNLEN, 1); redc(dEB.y.b, tmp); big_to_bytes(BNLEN, tmp, deB + BNLEN * 2, 1); redc(dEB.y.a, tmp); big_to_bytes(BNLEN, tmp, deB + BNLEN * 3, 1); free(Z); return 0;}/****************************************************************Function: SM9_EncryptDescription: SM9 encryption algorithmCalls: MIRACL functions,zzn12_init(),ecap(),member(),zzn12_ElementPrint(),zzn12_pow(),LinkCharZzn12(),SM3_KDF(),SM9_Enc_MAC(),SM4_Block_Encrypt()Called By: SM9_SelfCheck()Input:hid:0x03IDB //identification of userBmessage //the message to be encryptedlen //the length of messagerand //a random number K lies in [1,N-1]EncID //encryption identification,0:stream cipher 1:block cipherk1_len //the byte length of K1 in block cipher algorithmk2_len //the byte length of K2 in MAC algorithmPpubs //encrtption public keyOutput: C //cipher C1||C3||C2Clen //the byte length of CReturn:0: success1: asking for memory error2: element is out of order q3: R-ate calculation errorA: K1 equals 0Others:****************************************************************/int SM9_Encrypt(unsigned char hid[], unsigned char *IDB, unsigned char *message, int mlen, unsigned char rand[],int EncID, int k1_len, int k2_len, unsigned char Ppub[], unsigned char C[], int *C_len){ big h, x, y, r; zzn12 g, w; epoint *Ppube, *QB, *C1; unsigned char *Z = NULL, *K = NULL, *C2 = NULL, C3[SM3_len / 8]; int i = 0, j = 0, Zlen, buf, klen, C2_len; //initiate h = mirvar(0); r = mirvar(0); x = mirvar(0); y = mirvar(0); QB = epoint_init(); Ppube = epoint_init(); C1 = epoint_init(); zzn12_init(&g); zzn12_init(&w); bytes_to_big(BNLEN, Ppub, x); bytes_to_big(BNLEN, Ppub + BNLEN, y); epoint_set(x, y, 0, Ppube); //Step1:calculate QB=[H1(IDB||hid,N)]P1+Ppube Zlen = strlen(IDB) + 1; Z = (char *)malloc(sizeof(char)*(Zlen + 1)); if (Z == NULL) return SM9_ASK_MEMORY_ERR; memcpy(Z, IDB, strlen(IDB)); memcpy(Z + strlen(IDB), hid, 1); buf = SM9_H1(Z, Zlen, N, h); if (buf) return buf; ecurve_mult(h, P1, QB); ecurve_add(Ppube, QB); printf("\n*******************QB:=[H1(IDB||hid,N)]P1+Ppube*****************\n"); epoint_get(QB, x, y); cotnum(x, stdout); cotnum(y, stdout); //Step2:randnom bytes_to_big(BNLEN, rand, r); printf("\n***********************随机数 r:********************************\n"); cotnum(r, stdout); //Step3:C1=[r]QB ecurve_mult(r, QB, C1); printf("\n*************************:C1=[r]QB*******************************\n"); epoint_get(C1, x, y); cotnum(x, stdout); cotnum(y, stdout); big_to_bytes(BNLEN, x, C, 1); big_to_bytes(BNLEN, y, C + BNLEN, 1); //Step4:g = e(P2, Ppub-e) if (!ecap(P2, Ppube, para_t, X, &g)) return SM9_MY_ECAP_12A_ERR; //test if a ZZn12 element is of order q if (!member(g, para_t, X)) return SM9_MEMBER_ERR; printf("\n***********************g=e(P2,Ppube):****************************\n"); zzn12_ElementPrint(g); //Step5:calculate w=g^r w = zzn12_pow(g, r); printf("\n***************************w=g^r:**********************************\n"); zzn12_ElementPrint(w); free(Z); //Step6:calculate C2 if (EncID == 0) { //基于密钥派生函数的序列密码算法 //加密时间: 0.739000 seconds //解密时间: 0.156000 seconds C2_len = mlen; *C_len = BNLEN * 2 + SM3_len / 8 + C2_len; //Step:6-1: calculate K=KDF(C1||w||IDB,klen) klen = mlen + k2_len; Zlen = strlen(IDB) + BNLEN * 14; Z = (char *)malloc(sizeof(char)*(Zlen + 1)); K = (char *)malloc(sizeof(char)*(klen + 1)); C2 = (char *)malloc(sizeof(char)*(mlen + 1)); if (Z == NULL || K == NULL || C2 == NULL) return SM9_ASK_MEMORY_ERR; LinkCharZzn12(C, BNLEN * 2, w, Z, (Zlen - strlen(IDB))); memcpy(Z + BNLEN * 14, IDB, strlen(IDB)); SM3_KDF(Z, Zlen, klen, K); printf("\n*****************K=KDF(C1||w||IDB,klen):***********************\n"); for (i = 0; i

完整代码见github

参考文献

1、国标—SM9-加解密

2、密码学-基础理论与应用(李子臣著)

3、商用密码检测中心-源码下载

转载地址:http://yovez.baihongyu.com/

你可能感兴趣的文章
mysql 权限整理记录
查看>>
mysql 权限登录问题:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)
查看>>
MYSQL 查看最大连接数和修改最大连接数
查看>>
MySQL 查看有哪些表
查看>>
mysql 查看锁_阿里/美团/字节面试官必问的Mysql锁机制,你真的明白吗
查看>>
MySql 查询以逗号分隔的字符串的方法(正则)
查看>>
MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT 、分页查询的优化、合理使用连接、子查询的优化)(上)
查看>>
mysql 查询数据库所有表的字段信息
查看>>
【Java基础】什么是面向对象?
查看>>
mysql 查询,正数降序排序,负数升序排序
查看>>
MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)...
查看>>
mysql 死锁 Deadlock found when trying to get lock; try restarting transaction
查看>>
mysql 死锁(先delete 后insert)日志分析
查看>>
MySQL 死锁了,怎么办?
查看>>
MySQL 深度分页性能急剧下降,该如何优化?
查看>>
MySQL 深度分页性能急剧下降,该如何优化?
查看>>
MySQL 添加列,修改列,删除列
查看>>
mysql 添加索引
查看>>
MySQL 添加索引,删除索引及其用法
查看>>
mysql 状态检查,备份,修复
查看>>