大結局---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內使用國密推薦參數以及提供的一段明文:



執行效果:

(圖不完整,右邊還有很長的數據……)

解密成功!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM