#include "StdAfx.h" #include "sm2.h" #include "kdf.h" #include "public.h" static const char rnd_seed[] = "string to make the random number generator think it has entropy"; #pragma comment(lib,"libeay32.lib") BN_CTX *ctx = NULL; EC_GROUP *group; void BNPrintf(BIGNUM* bn) { char *p=NULL; p=BN_bn2hex(bn); printf("%s",p); OPENSSL_free(p); } int sm2_init() { BIGNUM *p, *a, *b; BIGNUM *x, *y, *z; EC_POINT *P, *Q; CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); ERR_load_crypto_strings(); RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */ /* 素数p:FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF 系数a:FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC 系数b:28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93 基点G: xG:32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7 yG:BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0 阶n:FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123 */ ctx = BN_CTX_new(); if (!ctx) ABORT; /* Curve SM2 (Chinese National Algorithm) */ //http://www.oscca.gov.cn/News/201012/News_1197.htm p = BN_new(); a = BN_new(); b = BN_new(); if (!p || !a || !b) ABORT; group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp * so that the library gets to choose the EC_METHOD */ if (!group) ABORT; if (!BN_hex2bn(&p, "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"))ABORT;//8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"))ABORT;//787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498")) ABORT; if (!BN_hex2bn(&b, "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"))ABORT;//63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; P = EC_POINT_new(group); Q = EC_POINT_new(group); if (!P || !Q) ABORT; x = BN_new(); y = BN_new(); z = BN_new(); if (!x || !y || !z) ABORT; if (!BN_hex2bn(&x, "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"))ABORT;//421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"))ABORT;//8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"))ABORT;//0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2")) ABORT; if (0 != BN_cmp(y, z)) ABORT; if (EC_GROUP_get_degree(group) != 256) ABORT; if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; EC_POINT_free(P); EC_POINT_free(Q); return 0; } EC_KEY* sm2_generate_key() { EC_KEY *tmpKey = NULL; if ((tmpKey = EC_KEY_new()) == NULL) return NULL; if (EC_KEY_set_group(tmpKey, group) == 0) { fprintf(stdout," failed\n"); return NULL; } if(EC_KEY_generate_key(tmpKey)!=1) { printf("EC_KEY_generate_key err.\n"); return NULL; } /* 检查密钥 */ if(EC_KEY_check_key(tmpKey)!=1) { printf("check key err.\n"); return NULL; } return tmpKey; } EC_POINT *sm2_compute_key(const EC_POINT *b_pub_key_r, const EC_POINT *b_pub_key, const BIGNUM *a_r,EC_KEY *a_eckey) { BN_CTX *ctx; EC_POINT *tmp=NULL; BIGNUM *x=NULL, *y=NULL, *order=NULL,*z=NULL; const BIGNUM *priv_key; const EC_GROUP* group; EC_POINT *ret= NULL; /* size_t buflen, len;*/ unsigned char *buf=NULL; int i, j; //char *p=NULL; BIGNUM *x1,*x2,*t,*h; if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); order = BN_CTX_get(ctx); z = BN_CTX_get(ctx); x1 = BN_CTX_get(ctx); x2 = BN_CTX_get(ctx); t = BN_CTX_get(ctx); h = BN_CTX_get(ctx); priv_key = EC_KEY_get0_private_key(a_eckey); if (priv_key == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_NO_PRIVATE_VALUE); goto err; } group = EC_KEY_get0_group(a_eckey); if ((tmp=EC_POINT_new(group)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, a_r, NULL, NULL, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, NULL, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } else { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, NULL, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB); goto err; } i = BN_num_bits(order); j = i/2 -1; BN_mask_bits(x,j); BN_set_word(y,2); BN_set_word(z,j); BN_exp(y,y,z,ctx); BN_add(x1,x,y); BN_mod_mul(t,x1,a_r,order,ctx); BN_mod_add_quick(t,t,priv_key,order); // if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, b_pub_key_r, x, NULL, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } else { if (!EC_POINT_get_affine_coordinates_GF2m(group, b_pub_key_r, x, NULL, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } i = BN_num_bits(order); j = i/2 -1; BN_mask_bits(x,j); BN_set_word(y,2); BN_set_word(z,j); BN_exp(y,y,z,ctx); BN_add(x2,x,y); //x2*Rb+Pb; if (!EC_POINT_mul(group, tmp, NULL,b_pub_key_r,x2,ctx) ) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } if ((ret=EC_POINT_new(group)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_add(group, ret, b_pub_key, tmp, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group,ret, x, y, ctx)) { goto err; } if(!EC_GROUP_get_cofactor(group, h, ctx)) { goto err; } BN_mul(t,t,h,ctx); //h*t*(x2*Rb+Pb) if (!EC_POINT_mul(group, ret, NULL,ret,t,ctx) ) { goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group,ret, x, y, ctx)) { goto err; } err: if (tmp) EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); if (ctx) BN_CTX_free(ctx); if (buf) OPENSSL_free(buf); return(ret); } int sm2_exchange_key(EC_KEY*B,EC_KEY*RB,EC_POINT*PA,EC_POINT*RA,unsigned char*ZA,unsigned char *ZB,unsigned char *outkey,size_t keylen) { EC_POINT *dhpoint = NULL; BN_CTX * ctx; BIGNUM *x, *y,*z; int ret = 0; unsigned char in[256],SB[33],tmp[33]={0}; int inlen; int len; ctx = BN_CTX_new(); x = BN_new(); y = BN_new(); z = BN_new(); if (!x || !y ||!z) goto err; z = (BIGNUM*)EC_KEY_get0_private_key(RB); dhpoint = sm2_compute_key(RA,PA,z,B); if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group,dhpoint, x, y, ctx)) { fprintf(stdout, " failed\n"); goto err; } } else { if (!EC_POINT_get_affine_coordinates_GF2m(group,dhpoint, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } fprintf(stdout, "\nTesting DH Point\n Xv = 0x"); BNPrintf(x); fprintf(stdout, "\n Yv = 0x"); BNPrintf( y); fprintf(stdout, "\n"); len = BN_bn2bin(x,in); inlen =BN_bn2bin(y,in+len); inlen = inlen + len; memcpy(in+inlen,ZA,32); inlen +=32; memcpy(in+inlen,ZB,32); inlen +=32; ret = sm3_kdf(in,inlen,keylen,outkey); //计算可选项 Hash(0x02||yv||Hash(xv||ZA||ZB||x1||y1||x2||y2)); BN_bn2bin(y,tmp); memset(in,0,sizeof(in)); len = BN_bn2bin(x,in); memcpy(in+len,ZA,32); len +=32; memcpy(in+len,ZB,32); len +=32; inlen = len; if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group,RA, x, y, ctx)) { fprintf(stdout, " failed\n"); goto err; } } else { if (!EC_POINT_get_affine_coordinates_GF2m(group,RA, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } len = BN_bn2bin(x,in+inlen); inlen +=len; len =BN_bn2bin(y,in+inlen); inlen += len; len = ecKey2str(RB,in+inlen); inlen += len; sm3(in,inlen,SB); memset(in,0,sizeof(in)); in[0] = 0x02; memcpy(in+1,tmp,32); memcpy(in+33,SB,32); sm3(in,65,SB); memcpy(outkey+keylen,SB,32); //ret = 1; err: EC_POINT_free(dhpoint); BN_CTX_free(ctx); return ret; return 0; } int sm2_end() { EC_GROUP_free(group); BN_CTX_free(ctx); CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); ERR_remove_state(0); CRYPTO_mem_leaks_fp(stderr); return 0; } int ecKey2str(EC_KEY*k,unsigned char*pubkey) { EC_POINT *point; BIGNUM *x,*y; int ilen = 0,tolen=0; unsigned char to[512] = {0}; x = BN_new(); y = BN_new(); point = (EC_POINT *)EC_KEY_get0_public_key(k); if (!EC_POINT_get_affine_coordinates_GFp(group,point, x, y, ctx)) ABORT; tolen = BN_bn2bin(x,to); memcpy(pubkey,to,tolen); ilen += tolen; tolen = BN_bn2bin(y,to); memcpy(pubkey+ilen,to,tolen); ilen +=tolen; return ilen; } int pubkey2ecPoint(char*pubkey,EC_POINT**k) { char tmp[65] = {0}; BIGNUM *x,*y; x = BN_new(); y = BN_new(); memcpy(tmp,pubkey,64); if(!BN_hex2bn(&x,(const char*)tmp))ABORT; memcpy(tmp,pubkey+64,64); if(!BN_hex2bn(&y,(const char*)tmp))ABORT; if(!EC_POINT_set_affine_coordinates_GFp(group,*k,x,y,ctx))ABORT; return 0; } /* random_k :随机数k,Ascii码表示的16进制字符串如:4C62EEFD6ECFC2B95B92FD6C3D9575148AFA17425546D49018E5388D49DD7B4F ecpoint_PBx:公钥的x值:435B39CCA8F3B508C1488AFC67BE491A0F7BA07E581A0E4849A5CF70628A7E0A ecpont_PBy:公钥的y值:75DDBA78F15FEECB4C7895E2C1CDF5FE01DEBB2CDBADF45399CCF77BBA076A42 M:要加密的信息,原文,不处理 encdata:加密后的返回值,已转为Ascii码形式 返回值:加密返回的字符串长度 */ int sm2_encrypt(char*random_k,char*ecpoint_PBx,char*ecpoint_PBy,const char *M,unsigned char mdatalen,char*encdata) /* 新国密密文格式加密 */ { int len,inlen,encLen = 0,mLen = 0; unsigned char in[512],outkey[256]={0},C2[256]={0}; BIGNUM *x,*y,*k; EC_POINT *C1,*P,*PB; unsigned char C3[256] = {0}; unsigned char tsm2data[256]; mLen = mdatalen; sm2_init(); x = BN_new(); y = BN_new(); k = BN_new(); C1 = EC_POINT_new(group); PB = EC_POINT_new(group); P = EC_POINT_new(group); if(!BN_hex2bn(&k,random_k))ABORT;//随机数k if(!EC_POINT_mul(group,C1,k,NULL,NULL,ctx))ABORT; if(!EC_POINT_get_affine_coordinates_GFp(group,C1,x,y,ctx))ABORT; /* printf("C1=[k]G:\r\n"); BNPrintf(x); BNPrintf(y); */ encdata[0] = 0x04; encLen = 1; memset(encdata+1,0,64); len = BN_bn2bin(x,tsm2data); memcpy(encdata+33-len,tsm2data,len); len=32; inlen = BN_bn2bin(y,tsm2data); memcpy(encdata+65-inlen,tsm2data,inlen); inlen=32; encLen += len + inlen; if(!BN_hex2bn(&x,ecpoint_PBx))ABORT;//xB if(!BN_hex2bn(&y,ecpoint_PBy))ABORT;//yB if(!EC_POINT_set_affine_coordinates_GFp(group,PB,x,y,ctx))ABORT; if(!EC_POINT_mul(group,P,NULL,PB,k,ctx))ABORT; if(!EC_POINT_get_affine_coordinates_GFp(group,P,x,y,ctx))ABORT; /* printf("P=[k]PB:\r\n"); BNPrintf(x); BNPrintf(y); */ memset(in,0,64); len = BN_bn2bin(x,tsm2data); memcpy(in+32-len,tsm2data,len); len=32; inlen =BN_bn2bin(y,tsm2data); memcpy(in+64-inlen,tsm2data,inlen); inlen = 64; sm3_kdf(in,inlen,mLen,outkey); for(len=0;len0 M的长度 =0 解密失败 */ int sm2_decrypt(const char*decdata,const char*dB,char*M) /* 旧国密密文格式解密 */ { int len,inlen,mLen = 0; unsigned char in[256],outkey[256]={0}; unsigned char C2[256]={0},C3[256]={0}; char xstr[65]={0},ystr[65]={0}; unsigned char tsm2data[256]; EC_POINT *C1,*S,*P; BIGNUM *x,*y,*h; x = BN_new(); y = BN_new(); h = BN_new(); sm2_init(); C1 = EC_POINT_new(group); S = EC_POINT_new(group); P = EC_POINT_new(group); memcpy(xstr,decdata+2,64); memcpy(ystr,decdata+66,64); len = strlen(decdata); mLen = len - 130 - 64; AsciiToHex((char*)decdata+130,C2,64); AsciiToHex((char*)decdata+len-64,C3,64); mLen /=2; /* memcpy(C2,decdata+130,mLen); memcpy(C3,decdata+len-64,64); */ if(!BN_hex2bn(&x,xstr))ABORT; if(!BN_hex2bn(&y,ystr))ABORT; if(!EC_POINT_set_affine_coordinates_GFp(group,C1,x,y,ctx))ABORT; /* printf("C1:\r\n"); BNPrintf(x); printf("\r\n"); BNPrintf(y); printf("\r\n"); */ if(!EC_POINT_is_on_curve(group,C1,ctx))ABORT; if(!EC_GROUP_get_cofactor(group,h,ctx))ABORT; if(!EC_POINT_mul(group,S,NULL,C1,h,ctx))ABORT; if(EC_POINT_is_at_infinity(group,S))ABORT; //S是无穷远点 if(!BN_hex2bn(&x,dB))ABORT; if(!EC_POINT_mul(group,P,NULL,C1,x,ctx))ABORT; if(!EC_POINT_get_affine_coordinates_GFp(group,P,x,y,ctx))ABORT; /* printf("P=[dB]C1:\r\n"); BNPrintf(x); printf("\r\n"); BNPrintf(y); printf("\r\n"); */ memset(in,0,64); len = BN_bn2bin(x,tsm2data); memcpy(in+32-len,tsm2data,len); len=32; inlen =BN_bn2bin(y,tsm2data); memcpy(in+64-inlen,tsm2data,inlen); inlen = 64; sm3_kdf(in,inlen,mLen,outkey); for(len=0;len0 M的长度 =0 解密失败 */ int sm2_decrypt_new(const char*decdata,const char*dB,char*M) /* 新国密密文格式解密 */ { int len,inlen,mLen = 0; unsigned char in[256],outkey[256]={0}; unsigned char C2[256]={0},C3[256]={0}; unsigned char tsm2data[256]; char xstr[65]={0},ystr[65]={0}; EC_POINT *C1,*S,*P; BIGNUM *x,*y,*h; x = BN_new(); y = BN_new(); h = BN_new(); sm2_init(); C1 = EC_POINT_new(group); S = EC_POINT_new(group); P = EC_POINT_new(group); memcpy(xstr,decdata,64); memcpy(ystr,decdata+64,64); len = strlen(decdata); mLen = len - 128 - 64; AsciiToHex((char*)decdata+128,C3,64); AsciiToHex((char*)decdata+128+64,C2,mLen); mLen /=2; /* memcpy(C2,decdata+130,mLen); memcpy(C3,decdata+len-64,64); */ if(!BN_hex2bn(&x,xstr))ABORT; if(!BN_hex2bn(&y,ystr))ABORT; if(!EC_POINT_set_affine_coordinates_GFp(group,C1,x,y,ctx))ABORT; /* printf("C1:\r\n"); BNPrintf(x); printf("\r\n"); BNPrintf(y); printf("\r\n"); */ if(!EC_POINT_is_on_curve(group,C1,ctx))ABORT; if(!EC_GROUP_get_cofactor(group,h,ctx))ABORT; if(!EC_POINT_mul(group,S,NULL,C1,h,ctx))ABORT; if(EC_POINT_is_at_infinity(group,S))ABORT; //S是无穷远点 if(!BN_hex2bn(&x,dB))ABORT; if(!EC_POINT_mul(group,P,NULL,C1,x,ctx))ABORT; if(!EC_POINT_get_affine_coordinates_GFp(group,P,x,y,ctx))ABORT; /* printf("P=[dB]C1:\r\n"); BNPrintf(x); printf("\r\n"); BNPrintf(y); printf("\r\n"); */ memset(in,0,64); len = BN_bn2bin(x,tsm2data); memcpy(in+32-len,tsm2data,len); len=32; inlen =BN_bn2bin(y,tsm2data); memcpy(in+64-inlen,tsm2data,inlen); inlen = 64; sm3_kdf(in,inlen,mLen,outkey); for(len=0;len