大结局---Miracl库下完全实现SM2加密算法
本次博文以前面的两次文章的函数定义、说明为基础进行扩展。
并且参考了一些其他的优秀博客文章,比如KDF局部密钥派生函数的使用、十六进制字符串与二进制字符串以及普通字符串转换函数(自己也编写了一部分函数)、SM3杂凑签名算法(太懒了,完全拿来用了,取其精华,感谢博客主人)。
完成本次实验前,进一步了解了C语言,这种直接面对内存进行操作的语言真的既让人爱又让人恨……
然后,介绍一下我实现本算法的大概思路:从文件读入等待加密的明文,然后以二进制字符串形式(字符数组,定义了很多中间变量,做好准备吧)构造密文,中间还涉及十六进制形式的字符串,因为我需要把字符串转成16进制再转成二进制,并且中间有很多操作也和十六进制形式有关。
最后,强调一下定义的这些函数都是对字符数组进行,然后把结果填充到另一个指定地址去,这种思想伴随了整个程序中……
sm3头文件代码(参考与网址 https://blog.csdn.net/a344288106/ article/details/80094878 ):
1 #include <stdio.h> 2 #include <memory.h> 3 #ifndef _SM3_H_ 4 #define _SM3_H_ 5 6 /* 7 * SM3算法产生的哈希值大小(单位:字节) 8 */ 9 #define SM3_HASH_SIZE 32 10 11 /* 12 * SM3上下文 13 */ 14 typedef struct SM3Context 15 { 16 unsigned int intermediateHash[SM3_HASH_SIZE / 4]; 17 unsigned char messageBlock[64]; 18 } SM3Context; 19 20 /* 21 * SM3计算函数 22 */ 23 unsigned char *SM3Calc(const unsigned char *message,unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]); 24 25 #endif // _SM3_H_ 26 /* 27 * 判断运行环境是否为小端 28 */ 29 static const int endianTest = 1; 30 #define IsLittleEndian() (*(char *)&endianTest == 1) 31 32 /* 33 * 向左循环移位 34 */ 35 #define LeftRotate(word, bits) ( (word) << (bits) | (word) >> (32 - (bits)) ) 36 37 /* 38 * 反转四字节整型字节序 39 */ 40 unsigned int *ReverseWord(unsigned int *word) 41 { 42 unsigned char *byte, temp; 43 44 byte = (unsigned char *)word; 45 temp = byte[0]; 46 byte[0] = byte[3]; 47 byte[3] = temp; 48 49 temp = byte[1]; 50 byte[1] = byte[2]; 51 byte[2] = temp; 52 return word; 53 } 54 55 /* 56 * T 57 */ 58 unsigned int T(int i) 59 { 60 if (i >= 0 && i <= 15) 61 return 0x79CC4519; 62 else if (i >= 16 && i <= 63) 63 return 0x7A879D8A; 64 else 65 return 0; 66 } 67 68 /* 69 * FF 70 */ 71 unsigned int FF(unsigned int X, unsigned int Y, unsigned int Z, int i) 72 { 73 if (i >= 0 && i <= 15) 74 return X ^ Y ^ Z; 75 else if (i >= 16 && i <= 63) 76 return (X & Y) | (X & Z) | (Y & Z); 77 else 78 return 0; 79 } 80 81 /* 82 * GG 83 */ 84 unsigned int GG(unsigned int X, unsigned int Y, unsigned int Z, int i) 85 { 86 if (i >= 0 && i <= 15) 87 return X ^ Y ^ Z; 88 else if (i >= 16 && i <= 63) 89 return (X & Y) | (~X & Z); 90 else 91 return 0; 92 } 93 94 /* 95 * P0 96 */ 97 unsigned int P0(unsigned int X) 98 { 99 return X ^ LeftRotate(X, 9) ^ LeftRotate(X, 17); 100 } 101 102 /* 103 * P1 104 */ 105 unsigned int P1(unsigned int X) 106 { 107 return X ^ LeftRotate(X, 15) ^ LeftRotate(X, 23); 108 } 109 110 /* 111 * 初始化函数 112 */ 113 void SM3Init(SM3Context *context) 114 { 115 context->intermediateHash[0] = 0x7380166F; 116 context->intermediateHash[1] = 0x4914B2B9; 117 context->intermediateHash[2] = 0x172442D7; 118 context->intermediateHash[3] = 0xDA8A0600; 119 context->intermediateHash[4] = 0xA96F30BC; 120 context->intermediateHash[5] = 0x163138AA; 121 context->intermediateHash[6] = 0xE38DEE4D; 122 context->intermediateHash[7] = 0xB0FB0E4E; 123 } 124 125 /* 126 * 处理消息块 127 */ 128 void SM3ProcessMessageBlock(SM3Context *context) 129 { 130 int i; 131 unsigned int W[68]; 132 unsigned int W_[64]; 133 unsigned int A, B, C, D, E, F, G, H, SS1, SS2, TT1, TT2; 134 135 /* 消息扩展 */ 136 //printf("扩展后的消息 W0-W67:\n"); 137 for (i = 0; i < 16; i++) 138 { 139 W[i] = *(unsigned int *)(context->messageBlock + i * 4); 140 if (IsLittleEndian()) 141 ReverseWord(W + i); 142 //if((i % 8) == 0) printf("%02d: ",i); 143 //printf(" %08x",W[i]); 144 //if(((i+1) % 8) == 0) printf("\n"); 145 } 146 for (i = 16; i < 68; i++) 147 { 148 W[i] = P1(W[i - 16] ^ W[i - 9] ^ LeftRotate(W[i - 3], 15)) 149 ^ LeftRotate(W[i - 13], 7) 150 ^ W[i - 6]; 151 //if((i % 8) == 0) printf("%02d: ",i); 152 //printf(" %08x", W[i]); 153 //if(((i+1) % 8) == 0) printf("\n"); 154 } 155 //printf("\n扩展后的消息 W'0-W'63:\n"); 156 for (i = 0; i < 64; i++) 157 { 158 W_[i] = W[i] ^ W[i + 4]; 159 //if((i % 8) == 0) printf("%02d: ",i); 160 //printf(" %08x",W_[i]); 161 //if(((i+1) % 8) == 0) printf("\n"); 162 } 163 164 /* 消息压缩 */ 165 A = context->intermediateHash[0]; 166 B = context->intermediateHash[1]; 167 C = context->intermediateHash[2]; 168 D = context->intermediateHash[3]; 169 E = context->intermediateHash[4]; 170 F = context->intermediateHash[5]; 171 G = context->intermediateHash[6]; 172 H = context->intermediateHash[7]; 173 //printf("迭代压缩中间值:\n"); 174 //printf("i A B C D E F G H\n"); 175 //printf(" %08x %08x %08x %08x %08x %08x %08x %08x\n",A,B,C,D,E,F,G,H); 176 for (i = 0; i < 64; i++) 177 { 178 SS1 = LeftRotate((LeftRotate(A, 12) + E + LeftRotate(T(i), i)), 7); 179 SS2 = SS1 ^ LeftRotate(A, 12); 180 TT1 = FF(A, B, C, i) + D + SS2 + W_[i]; 181 TT2 = GG(E, F, G, i) + H + SS1 + W[i]; 182 D = C; 183 C = LeftRotate(B, 9); 184 B = A; 185 A = TT1; 186 H = G; 187 G = LeftRotate(F, 19); 188 F = E; 189 E = P0(TT2); 190 //printf("%02d %08x %08x %08x %08x %08x %08x %08x %08x\n",i,A,B,C,D,E,F,G,H); 191 } 192 context->intermediateHash[0] ^= A; 193 context->intermediateHash[1] ^= B; 194 context->intermediateHash[2] ^= C; 195 context->intermediateHash[3] ^= D; 196 context->intermediateHash[4] ^= E; 197 context->intermediateHash[5] ^= F; 198 context->intermediateHash[6] ^= G; 199 context->intermediateHash[7] ^= H; 200 } 201 202 /* 203 * SM3算法主函数 204 */ 205 unsigned char *SM3Calc(const unsigned char *message,unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]) 206 { 207 208 SM3Context context; 209 unsigned int i, remainder, bitLen; 210 /* 初始化上下文 */ 211 SM3Init(&context); 212 213 /* 对前面的消息分组进行处理 */ 214 for (i = 0; i < messageLen / 64; i++) //i是Bi分组数目(512bits),只有一组则不处理,因为0< 0不成立 215 { 216 memcpy(context.messageBlock, message + i * 64, 64); 217 SM3ProcessMessageBlock(&context); 218 } 219 220 /* 填充消息分组,并处理 */ 221 bitLen = messageLen * 8; //消息的比特长度,用于待会的填充 222 if (IsLittleEndian()) 223 ReverseWord(&bitLen); 224 remainder = messageLen % 64; 225 memcpy(context.messageBlock, message + i * 64, remainder); 226 context.messageBlock[remainder] = 0x80; 227 if (remainder <= 55) 228 { 229 memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1 - 8 + 4); 230 memcpy(context.messageBlock + 64 - 4, &bitLen, 4); //最后四字节存放信息长度 231 SM3ProcessMessageBlock(&context); 232 } 233 else 234 { 235 memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1);//本组余下的全填零 236 SM3ProcessMessageBlock(&context); 237 memset(context.messageBlock, 0, 64 - 4); 238 memcpy(context.messageBlock + 64 - 4, &bitLen, 4); 239 SM3ProcessMessageBlock(&context); 240 } 241 242 /* 返回结果 */ 243 if (IsLittleEndian()) 244 for (i = 0; i < 8; i++) 245 ReverseWord(context.intermediateHash + i); 246 memcpy(digest,context.intermediateHash, SM3_HASH_SIZE); 247 248 return digest; 249 }
下面是KDF函数定义(参考与网址https://blog.csdn.net/heidlyn/article/details/53993002 )
1 int KDF(const char* cdata, int datalen, int keybitlen, char* retdata) 2 { 3 int nRet = -1; 4 char* hexstring[512]={0}; 5 char* bytestring[256]={0}; 6 unsigned char *pRet; 7 unsigned char *pData; 8 unsigned char cdgst[32]={0}; 9 unsigned char cCnt[4] = {0}; 10 int nCnt = 1; 11 int nDgst = 32; 12 int keybytelen=keybitlen/8; //keybytelen是明文(未来密钥)的字节长度 13 int nTimes = (keybytelen+31)/32; 14 int i=0; 15 if(cdata==NULL || datalen<=0 || keybitlen<=0) 16 goto err; 17 if(NULL == (pRet=(unsigned char *)malloc(keybytelen))) 18 goto err; 19 if(NULL == (pData=(unsigned char *)malloc(datalen+4))) 20 goto err; 21 memset(pRet, 0, keybytelen); 22 memset(pData, 0, datalen+4); 23 memcpy(pData, cdata, datalen); 24 for(; i<nTimes; i++) 25 { 26 cCnt[0] = (nCnt>>24) & 0xFF; 27 cCnt[1] = (nCnt>>16) & 0xFF; 28 cCnt[2] = (nCnt>> 8) & 0xFF; 29 cCnt[3] = (nCnt ) & 0xFF; 30 memcpy(pData+datalen, cCnt, 4); 31 Bin2Hex(pData,hexstring,datalen+4);//二进制字符串长度为datalen+4 32 Hex2Byte(hexstring,bytestring,datalen/4+1);//十六进制字符串长度为1/4(datalen+4) 33 SM3Calc(bytestring,(datalen+4)/8,cdgst); //字符串长度为1/8(datalen+4);应该传入字符串bytestring,而非比特串 34 if(i == nTimes-1) //最后一次计算,根据keybytelen/32是否整除,截取摘要的值 35 if(keybytelen%32 != 0) 36 nDgst = keybytelen%32; 37 memcpy(pRet+32*i, cdgst, nDgst); 38 nCnt ++; //计数器 39 } 40 bzero(hexstring,sizeof(hexstring)); 41 Str2Hex(pRet,hexstring,keybytelen); 42 Hex2Bin(hexstring,retdata,strlen(hexstring)); 43 nRet = 0; 44 err: 45 if(pRet) 46 free(pRet); 47 if(pData) 48 free(pData); 49 50 return nRet; 51 }
好的,下面就是SM2主函数加解密代码:
1 int main(){ //前面定义很多变量,不再一一介绍,后面用到再提 2 big a,b,p,Gx,Gy,n,db,k; 3 big x1,y1,x2,y2; 4 int kbitlen; 5 char plain[1024]={0}; //存放文件中读取的明文字符串 6 char plain_bin[8192]={0}; //存放明文的二进制字符串 7 char C2_bin[8192]={0}; //存放解密出明文的二进制字符串 8 char sm3_dgst[33]={0}; //存放 sm3 32字节的杂凑摘要 9 char crypt[3072]={0}; //存放加密生成的密文的二进制形式 10 char Hexstring1[65]={0}; 11 char Hexstring2[65]={0}; 12 char Hexstring3[2048]={0}; 13 char HexTemp[2048]={0}; 14 char t1[8192]={0}; 15 char Binarystring1[257]={0}; 16 char Binarystring2[257]={0}; 17 char Binarystring3[513]={0}; 18 FILE *fp; //存放的文件存放推荐的参数a、b、p、Gx、Gy、n等等 19 FILE *input_string;//存放明文 20 epoint* G=NULL; //基点G 21 epoint* Pb=NULL; //公钥点Pb 22 epoint* T1=NULL; //点T1(x1,y1)=[k]G 23 epoint* T2=NULL; 24 epoint* D1=NULL; 25 epoint* D2=NULL; 26 miracl* mip=mirsys(1000,16);//初始化大数库 27 a=mirvar(0); 28 b=mirvar(0); 29 p=mirvar(0); //p 256 bits 30 Gx=mirvar(0); 31 Gy=mirvar(0); 32 n=mirvar(0); 33 k=mirvar(0); 34 db=mirvar(0);//用户私钥数字 35 x1=mirvar(0); 36 y1=mirvar(0); 37 x2=mirvar(0); 38 y2=mirvar(0); 39 fp=fopen("abp.txt","r+"); //fp指向同目录下存放参数的文件 40 if(fp==0) 41 { 42 printf("文件打开失败!"); 43 exit(1); 44 } 45 mip->IOBASE=16;//下面依次读取十六进制的参数 46 cinnum(a,fp); 47 cinnum(b,fp); 48 cinnum(p,fp); 49 cinnum(Gx,fp); 50 cinnum(Gy,fp); 51 cinnum(n,fp); 52 fclose(fp);//关闭参数文件指针 53 system("color E"); 54 printf("---------参数生成---------\n"); //打印已知参数 55 printf("参数a="); 56 cotnum(a,stdout); 57 printf("参数b="); 58 cotnum(b,stdout); 59 printf("有限域素数p="); 60 cotnum(p,stdout); 61 printf("基点横坐标Gx="); 62 cotnum(Gx,stdout); 63 printf("基点纵坐标Gy="); 64 cotnum(Gy,stdout); 65 printf("基点的阶n="); 66 cotnum(n,stdout); 67 bigrand(n,db); //db<n-1,随机生成私钥,然后打印 68 printf("选取私钥数字db="); 69 cotnum(db,stdout); 70 ecurve_init(a,b,p,MR_PROJECTIVE);//定义、初始化曲线方程 71 G=epoint_init(); 72 Pb=epoint_init();//初始化重要的点 73 T1=epoint_init(); 74 T2=epoint_init(); 75 if(epoint_set(Gx,Gy,0,G)) //验证、生成基点 G 76 printf("基点G生成成功\n"); 77 else{ 78 printf("基点G生成失败!\n"); return 1; 79 } 80 ecurve_mult(db,G,Pb); //Pb=db * G ,倍点运算----点的乘法函数 81 printf("公钥点Pb生成成功!\n"); 82 printf("--------------加密过程---------------\n"); 83 bigrand(n,k); //k<n 随机生成k,然后打印 84 printf("选取随机数k="); 85 cotnum(k,stdout); 86 ecurve_mult(k,G,T1); //生成点T1坐标(x1,y1)=[k]G 87 printf("点T1生成成功!\n"); 88 epoint_get(T1,x1,y1);//获取点x1、y1坐标 89 cotstr(x1,Hexstring1);//x1存入十六进制字符串数组 90 cotstr(y1,Hexstring2);//y1存入十六进制字符串数组 91 //用函数把十六进制转成二进制 92 Hex2Bin(Hexstring1,Binarystring1,strlen(Hexstring1)); 93 Hex2Bin(Hexstring2,Binarystring2,strlen(Hexstring2)); 94 //把C1 即x1|y1填入密文二进制数组最开始的部分 95 sprintf(crypt,"%s%s",Binarystring1,Binarystring2); 96 printf("\n目前的密文长度为:%d,内容:\n",strlen(crypt)); 97 puts(crypt); 98 bzero(Hexstring1,sizeof(Hexstring1));//清空一下用过的中间数组 99 bzero(Hexstring2,sizeof(Hexstring2)); 100 bzero(Binarystring1,sizeof(Binarystring1)); 101 bzero(Binarystring2,sizeof(Binarystring2)); 102 input_string=fopen("input.txt","r+");//从文件读取明文字符串 103 fgets(plain,sizeof(plain),input_string); 104 fclose(input_string); 105 //printf("请输入明文字符串:");//可以自己输入 106 //gets(plain); 107 kbitlen=strlen(plain)*8; //明文bit长度 108 printf("输入明文是%s,明文比特长度为%d.\n",plain,kbitlen); 109 //将明文以二进制形式填充进plain_bin字符串内 110 Str2Hex(plain,Hexstring3,strlen(plain)); 111 //Hexstring3只是一个中间媒介,存放明文16进制信息,后面用得到!!! 112 Hex2Bin(Hexstring3,plain_bin,strlen(Hexstring3)); 113 ecurve_mult(k,Pb,T2); //T2坐标(x2,y2)=[k]Pb 114 printf("点T2生成成功!\n"); 115 epoint_get(T2,x2,y2); 116 cotstr(x2,Hexstring1); 117 cotstr(y2,Hexstring2); 118 //HexTemp存放十六进制形式的 x2|M|y2 119 sprintf(HexTemp,"%s%s%s",Hexstring1,Hexstring3,Hexstring2); 120 Hex2Bin(Hexstring1,Binarystring1,strlen(Hexstring1)); 121 Hex2Bin(Hexstring2,Binarystring2,strlen(Hexstring2)); 122 //Binarystring3目前存放x2|y2,用于后面的KDF计算 123 sprintf(Binarystring3,"%s%s",Binarystring1,Binarystring2); 124 bzero(Hexstring1,sizeof(Hexstring1)); //清空一波 125 bzero(Hexstring2,sizeof(Hexstring2)); 126 bzero(Hexstring3,sizeof(Hexstring3)); 127 bzero(Binarystring1,sizeof(Binarystring1)); 128 bzero(Binarystring2,sizeof(Binarystring2)); 129 //返回结果t1存放kbitlen长度的密钥 130 KDF(Binarystring3,512,kbitlen,t1); 131 if(strlen(plain_bin)==strlen(t1)) 132 printf("长度一致,可以进行异或!\n"); 133 //把C2 = t1^M 填充到最后的密文中,如果成功返回值应该是0 134 if(Bin_XOR(plain_bin,t1,crypt+strlen(crypt))!=0) 135 printf("异或出错!"); 136 printf("\n目前的密文长度为:%d,内容:\n",strlen(crypt)); 137 puts(crypt); 138 bzero(t1,sizeof(t1)); 139 bzero(plain,sizeof(plain));//销毁明文字符串数组,保证解密准确性 140 //暂时拿plain存放byte形式的C2:x2|M|y2 141 Hex2Byte(HexTemp,plain,strlen(HexTemp)); 142 bzero(HexTemp,sizeof(HexTemp)); 143 //计算sm3哈希值C3 = Hash(x2 ∥ M ∥ y2),存放到sm3_dgst byte类型 144 SM3Calc(plain,strlen(plain),sm3_dgst); 145 Str2Hex(sm3_dgst,Hexstring1,strlen(sm3_dgst)); 146 //哈希结果转二进制类型,写入密文crypt的中间部分 147 Hex2Bin(Hexstring1,crypt+strlen(crypt),strlen(Hexstring1)); 148 bzero(Hexstring1,sizeof(Hexstring1)); 149 printf("\n目前的密文长度为:%d,至此,加密成功!密文内容:\n",strlen(crypt)); 150 puts(crypt); 151 //后续处理,清空一切不需要的数组,只保留必要的信息 152 bzero(plain,sizeof(plain)); bzero(plain_bin,sizeof(plain_bin)); 153 bzero(sm3_dgst,sizeof(sm3_dgst)); 154 epoint_free(T1); 155 epoint_free(T2);//释放epoint类型点坐标 156 x1=mirvar(0); 157 y1=mirvar(0);//坐标值清零,后面还会用到 158 x2=mirvar(0); 159 y2=mirvar(0); 160 printf("------------解密过程--------------\n"); 161 printf("现在知道的信息有:收到的密文crypt\n C1部分长度为512bits,分别存储x1、y1的坐标信息\n kbitlen:代表明文的比特长度,对应密文C2部分的长度\n 解密者自己的私钥db\n"); 162 strncpy(Binarystring1,crypt,256); // x1二进制 163 strncpy(Binarystring2,crypt+256,256); // y1二进制 164 Bin2Hex(Binarystring1,Hexstring1,256); // x1十六进制 165 Bin2Hex(Binarystring2,Hexstring2,256); // y1十六进制 166 mip->IOBASE=16; 167 cinstr(x1,Hexstring1); 168 cinstr(y1,Hexstring2); 169 bzero(Binarystring1,sizeof(Binarystring1)); 170 bzero(Binarystring2,sizeof(Binarystring2)); 171 bzero(Hexstring1,sizeof(Hexstring1)); 172 bzero(Hexstring2,sizeof(Hexstring2)); 173 D1=epoint_init(); //初始化解密过程中将要用到的点 174 D2=epoint_init(); 175 if(epoint_set(x1,y1,0,D1)) 176 printf("点D1生成成功\n"); 177 else{ 178 printf("点D1生成失败!\n"); 179 return 0; 180 } 181 ecurve_mult(db,D1,D2); //点乘得到D2,解密非常关键的一步!!! 182 epoint_get(D2,x2,y2); //获取D2坐标信息一直转到二进制类型 183 cotstr(x2,Hexstring1); cotstr(y2,Hexstring2); 184 Hex2Bin(Hexstring1,Binarystring1,strlen(Hexstring1)); 185 Hex2Bin(Hexstring2,Binarystring2,strlen(Hexstring2)); 186 sprintf(Binarystring3,"%s%s",Binarystring1,Binarystring2);//Binarystring3目前存放x2|y2 187 bzero(Hexstring3,sizeof(Hexstring3)); 188 bzero(Binarystring1,sizeof(Binarystring1)); 189 bzero(Binarystring2,sizeof(Binarystring2)); 190 //计算t1=KDF(x2' ∥ y2', klen) 191 KDF(Binarystring3,512,kbitlen,t1); 192 bzero(Binarystring3,sizeof(Binarystring3)); 193 //从C中取出比特串C2bin,计算M ′ = C2 ⊕ t' 194 strncpy(C2_bin,crypt+512,kbitlen); 195 Bin_XOR(t1,C2_bin,plain_bin); // M'是 二进制 plain_bin 196 //M'是 十六进制 Hexstring3 197 Bin2Hex(plain_bin,Hexstring3,strlen(plain_bin)); 198 //HexTemp 存放hex形式的 x2|M'|y2 199 sprintf(HexTemp,"%s%s%s",Hexstring1,Hexstring3,Hexstring2); 200 bzero(Hexstring1,sizeof(Hexstring1)); 201 bzero(Hexstring2,sizeof(Hexstring2)); 202 // 拿plain存放字符串形式的C2:x2|M'|y2 203 Hex2Byte(HexTemp,plain,strlen(HexTemp)); 204 // u = Hash(x2 ∥ M '∥ y2) 还是存在变量sm3_dgst内 205 SM3Calc(plain,strlen(plain),sm3_dgst); 206 // u转成16进制hash值 207 Str2Hex(sm3_dgst,Hexstring1,strlen(sm3_dgst)); 208 // u转成二进制 256 bits hash值 209 Hex2Bin(Hexstring1,Binarystring1,strlen(Hexstring1)); 210 //从密文里面提取出最后的一部分信息赋给Binarystring2 211 strncpy(Binarystring2,crypt+512+kbitlen,256); 212 if(strcmp(Binarystring1,Binarystring2)==0){ //匹配 213 printf("*********************匹配成功!!!!**********************\n"); 214 bzero(plain,sizeof(plain)); 215 Hex2Byte(Hexstring3,plain,strlen(Hexstring3)); 216 printf("解密得到:\n"); 217 puts(plain); 218 } 219 bzero(Hexstring3,sizeof(Hexstring3)); 220 bzero(Hexstring1,sizeof(Hexstring1)); 221 bzero(plain,sizeof(plain)); 222 bzero(Binarystring1,sizeof(Binarystring1)); 223 printf("----------------------------结束----------------------------\n"); //后续处理 224 mirkill(a); 225 mirkill(b); 226 mirkill(p); 227 mirkill(n); 228 mirkill(Gx); 229 mirkill(Gy); 230 mirkill(db); 231 mirkill(k); 232 mirkill(x1); 233 mirkill(x2); 234 mirkill(y1); 235 mirkill(y2); 236 epoint_free(G); 237 epoint_free(Pb); 238 epoint_free(D1); 239 epoint_free(D2); 240 mirexit(); 241 return 0; 242 }
abp.txt内使用国密推荐参数以及提供的一段明文:
执行效果:
(图不完整,右边还有很长的数据……)
解密成功!