zoukankan      html  css  js  c++  java
  • 大结局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内使用国密推荐参数以及提供的一段明文:



    执行效果:

    (图不完整,右边还有很长的数据……)

    解密成功!

  • 相关阅读:
    数字三角形
    嵌套矩阵问题
    NKOJ1236 a^b
    历届试题 最大子阵
    【动态规划】最大连续子序列和,最大子矩阵和,最大m子段和
    历届试题 翻硬币
    历届试题 带分数
    用户模板和用户场景
    学习进度——第九周
    最大子数组——回调
  • 原文地址:https://www.cnblogs.com/Higgerw/p/10225943.html
Copyright © 2011-2022 走看看