<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      20231302邱之釗密碼系統設計實驗二一

      《密碼系統設計》實驗二

      在 Ubuntu或openEuler中(推薦 openEuler)中調試運?商?密碼檢測中?https://www.scctc.org.cn/xzzx/sfydm/ydmxz/提供的源代碼,?少運?SM2,SM3,SM4代碼。使?GmSSL命令驗證你代碼的正確性。使?Markdown記錄詳細記錄實踐過程,每完成?項功能或者?個函數git commit ?次。(14分)

      (一)SM2的實踐

      由于miracl庫存在問題,反復嘗試無法編譯,故參考鏈接進行實踐:
      https://github.com/lookingforfyf/SMX_Test/tree/master

      qzz@qzz-virtual-machine:~/Desktop/sy2/sm2/SMX_Test-master/SMX_Test/miracl-lib-X86_64/SM2ALG$ make
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm2/SMX_Test-master/SMX_Test/miracl-lib-X86_64/SM2ALG$ ./sm2_test
      ==============================================================================
      message  = 6D65737361676520646967657374 [for test sign]
      data     = 656E6372797074696F6E207374616E64617264 [for test enc]
      privkey  = 3945208F7B2144B13F36E38AC6D39F95889393692860B51A42FB81EF4DF7C5B8
      pubx     = 09F9DF311E5421A150DD7D161E4BC5C672179FAD1833FC076BB08FF356F35020
      puby     = CCEA490CE26775A52DC6EA718CC1AA600AED05FBF35E084A6632F6072DA9AD13
      rand     = 59276E27D506861A16680F3AD9C02DCCEF3CC1FA3CDBE4CE6D54B80DEAC1BC21
      ZA       = B2E14C5C79C6DF5B85F4FE7ED8DB7A262B9DA7E07CCB0EA9F4747B8CCDA8A4F3
      sign_R   = F5A03B0648D2C4630EEAC513E1BB81A15944DA3827D5B74143AC7EACEEE720B3
      sign_S   = B1B6AA29DF212FD8763182BC0D421CA1BB9038FD1F7F42D4840B69C485BBC1AA
      cipher   = 04EBFC718E8D1798620432268E77FEB6415E2EDE0E073C0F4F640ECD2E149A73
                 E858F9D81E5430A57B36DAAB8F950A3C64E6EE6A63094D99283AFF767E124DF0
                 59983C18F809E262923C53AEC295D30383B54E39D609D160AFCB1908D0BD8766
                 21886CA989CA9C7D58087307CA93092D651EFA
      ==============================================================================
      
      generate privkey = 3945208F7B2144B13F36E38AC6D39F95889393692860B51A42FB81EF4DF7C5B8 [pass]
      generate pubx    = 09F9DF311E5421A150DD7D161E4BC5C672179FAD1833FC076BB08FF356F35020 [pass]
      generate puby    = CCEA490CE26775A52DC6EA718CC1AA600AED05FBF35E084A6632F6072DA9AD13 [pass]
      generate ZA      = B2E14C5C79C6DF5B85F4FE7ED8DB7A262B9DA7E07CCB0EA9F4747B8CCDA8A4F3 [pass]
      generate sign_r  = F5A03B0648D2C4630EEAC513E1BB81A15944DA3827D5B74143AC7EACEEE720B3 [pass]
      generate sign_s  = B1B6AA29DF212FD8763182BC0D421CA1BB9038FD1F7F42D4840B69C485BBC1AA [pass]
      generate cipher  = 04EBFC718E8D1798620432268E77FEB6415E2EDE0E073C0F4F640ECD2E149A73 [pass]
                         E858F9D81E5430A57B36DAAB8F950A3C64E6EE6A63094D99283AFF767E124DF0
                         59983C18F809E262923C53AEC295D30383B54E39D609D160AFCB1908D0BD8766
                         21886CA989CA9C7D58087307CA93092D651EFA
      
      

      截圖如下:
      image

      (二)SM3的實踐

      sm3.h

      //
      // Created by He-Zh on 2024/10/27.
      //
      
      #ifndef EXP2_SM3_H
      #define EXP2_SM3_H
      #include <string.h>
      #define SM3_len 256
      #define SM3_T1 0x79CC4519
      #define SM3_T2 0x7A879D8A
      #define SM3_IVA 0x7380166f
      #define SM3_IVB 0x4914b2b9
      #define SM3_IVC 0x172442d7
      #define SM3_IVD 0xda8a0600
      #define SM3_IVE 0xa96f30bc
      #define SM3_IVF 0x163138aa
      #define SM3_IVG 0xe38dee4d
      #define SM3_IVH 0xb0fb0e4e
      /* Various logical functions */
      #define SM3_p1(x) (x^SM3_rotl32(x,15)^SM3_rotl32(x,23))
      #define SM3_p0(x) (x^SM3_rotl32(x,9)^SM3_rotl32(x,17))
      #define SM3_ff0(a,b,c) (a^b^c)
      #define SM3_ff1(a,b,c) ((a&b)|(a&c)|(b&c))
      #define SM3_gg0(e,f,g) (e^f^g)
      #define SM3_gg1(e,f,g) ((e&f)|((~e)&g))
      #define SM3_rotl32(x,n) ((((unsigned int) x) << n) | (((unsigned int) x) >> (32 - n)))
      #define SM3_rotr32(x,n) ((((unsigned int) x) >> n) | (((unsigned int) x) << (32 - n)))
      typedef struct {
          unsigned int state[8];
          unsigned int length;
          unsigned int curlen;
          unsigned char buf[64];
      } SM3_STATE;
      void BiToWj(unsigned int Bi[], unsigned int Wj[]);
      void WjToWj1(unsigned int Wj[], unsigned int Wj1[]);
      void CF(unsigned int Wj[], unsigned int Wj1[], unsigned int V[]);
      void BigEndian(unsigned char src[], unsigned int bytelen, unsigned char des[]);
      void SM3_init(SM3_STATE *md);
      void SM3_compress(SM3_STATE * md);
      void SM3_process(SM3_STATE * md, unsigned char buf[], int len);
      void SM3_done(SM3_STATE *md, unsigned char *hash);
      void SM3_256(unsigned char buf[], int len, unsigned char hash[]);
      int SM3_SelfTest();
      #endif //EXP2_SM3_H
      

      sm3.c

      //
      // Created by He-Zh on 2024/10/27.
      //
      
      #include "sm3.h"
      #include <stdio.h>
      void BiToW(unsigned int Bi[], unsigned int W[])
      {
          int i;
          unsigned int tmp;
          for(i=0;i<=15;i++)
          {
              W[i]=Bi[i];
          }
          for(i=16;i<=67;i++)
          {
              tmp=W[i-16]
                  ^ W[i-9]
                  ^ SM3_rotl32(W[i-3],15);
              W[i]=SM3_p1(tmp)
                   ^ (SM3_rotl32(W[i-13],7))
                   ^ W[i-6];
          }
      }
      void WToW1(unsigned int W[], unsigned int W1[])
      {
          int i;
          for(i=0;i<=63;i++)
          {
              W1[i]=W[i]^W[i+4];
          }
      }
      void CF(unsigned int W[], unsigned int W1[], unsigned int V[])
      {
          unsigned int SS1;
          unsigned int SS2;
          unsigned int TT1;
          unsigned int TT2;
          unsigned int A,B,C,D,E,F,G,H;
          unsigned int T=SM3_T1;
          unsigned int FF;
          unsigned int GG;
          int j;
      //reg init,set ABCDEFGH=V0
          A=V[0];
          B=V[1];
          C=V[2];
          D=V[3];
          E=V[4];
          F=V[5];
          G=V[6];
          H=V[7];
          for(j=0;j<=63;j++)
          {
              //SS1
              if(j==0)
              {
                  T=SM3_T1;
              }
              else if(j==16)
              {
                  T=SM3_rotl32(SM3_T2,16);
              }
              else
              {
                  T=SM3_rotl32(T,1);
              }
              SS1=SM3_rotl32((SM3_rotl32(A,12)+E+T),7);
              //SS2
              SS2=SS1^SM3_rotl32(A,12);
              //TT1
              if(j<=15)
              {
                  FF=SM3_ff0(A,B,C);
              }
              else
              {
                  FF=SM3_ff1(A,B,C);
              }
              TT1=FF+D+SS2+*W1;
              W1++;
              //TT2
              if(j<=15)
              {
                  GG=SM3_gg0(E,F,G);
              }
              else
              {
                  GG=SM3_gg1(E,F,G);
              }
              TT2=GG+H+SS1+*W;
              W++;
              //D
              D=C;
              //C
              C=SM3_rotl32(B,9);
              //B
              B=A;
              //A
              A=TT1;
              //H
              H=G;
              //G
              G=SM3_rotl32(F,19);
              //F
              F=E;
              //E
              E=SM3_p0(TT2);
          }
          //update V
          V[0]=A^V[0];
          V[1]=B^V[1];
          V[2]=C^V[2];
          V[3]=D^V[3];
          V[4]=E^V[4];
          V[5]=F^V[5];
          V[6]=G^V[6];
          V[7]=H^V[7];
      }
      void BigEndian(unsigned char src[], unsigned int bytelen, unsigned char des[])
      {
          unsigned char tmp = 0;
          unsigned int i = 0;
          for(i=0; i<bytelen/4; i++)
          {
              tmp = des[4*i];
              des[4*i] = src[4*i+3];
              src[4*i+3] = tmp;
              tmp = des[4*i+1];
              des[4*i+1] = src[4*i+2];
              des[4*i+2] = tmp;
          }
      }
      void SM3_init(SM3_STATE *md)
      {
          md->curlen = md->length = 0;
          md->state[0] = SM3_IVA;
          md->state[1] = SM3_IVB;
          md->state[2] = SM3_IVC;
          md->state[3] = SM3_IVD;
          md->state[4] = SM3_IVE;
          md->state[5] = SM3_IVF;
          md->state[6] = SM3_IVG;
          md->state[7] = SM3_IVH;
      }
      void SM3_compress(SM3_STATE * md)
      {
          unsigned int W[68];
          unsigned int W1[64];
          //if CPU uses little-endian, BigEndian function is a necessary call
          BigEndian(md->buf, 64, md->buf);
          BiToW((unsigned int *)md->buf,W);
          WToW1(W,W1);
          CF(W, W1, md->state);
      }
      void SM3_process(SM3_STATE * md, unsigned char *buf, int len)
      {
          while (len--)
          {
              /* copy byte */
              md->buf[md->curlen] = *buf++;
              md->curlen++;
              /* is 64 bytes full? */
              if (md->curlen == 64)
              {
                  SM3_compress(md);
                  md->length += 512;
                  md->curlen = 0;
              }
          }
      }
      void SM3_done(SM3_STATE *md, unsigned char hash[])
      {
          int i;
          unsigned char tmp = 0;
          /* increase the bit length of the message */
          md->length += md->curlen <<3;
          /* append the '1' bit */
          md->buf[md->curlen] = 0x80;
          md->curlen++;
          /* if the length is currently above 56 bytes, appends zeros till
          it reaches 64 bytes, compress the current block, creat a new
          block by appending zeros and length,and then compress it
          */
          if (md->curlen >56)
          {
              for (; md->curlen < 64;)
              {
                  md->buf[md->curlen] = 0;
                  md->curlen++;
              }
              SM3_compress(md);
              md->curlen = 0;
          }
          /* if the length is less than 56 bytes, pad upto 56 bytes of zeroes */
          for (; md->curlen < 56;)
          {
              md->buf[md->curlen] = 0;
              md->curlen++;
          }
          /* since all messages are under 2^32 bits we mark the top bits zero */
          for (i = 56; i < 60; i++)
          {
              md->buf[i] = 0;
          }
          /* append length */
          md->buf[63] = md->length & 0xff;
          md->buf[62] = (md->length >> 8) & 0xff;
          md->buf[61] = (md->length >> 16) & 0xff;
          md->buf[60] = (md->length >> 24) & 0xff;
          SM3_compress(md);
          /* copy output */
          memcpy(hash,md->state,SM3_len/8);
          BigEndian(hash,SM3_len/8,hash);//if CPU uses little-endian, BigEndian function is a necessary call
      }
      void SM3_256(unsigned char buf[], int len, unsigned char hash[])
      {
          SM3_STATE md;
          SM3_init(&md);
          SM3_process(&md, buf, len);
          SM3_done(&md, hash);
      }
      int SM3_SelfTest()
      {
          unsigned int i=0,a=1,b=1;
          
          // 測試用例1:字符串 "20231302邱之釗"
          unsigned char Msg1[] = "20231302邱之釗";
          int MsgLen1 = strlen((char*)Msg1);
          unsigned char MsgHash1[32] = {0};
          
          // 測試用例2:原來的長字符串測試(可選保留)
          unsigned char Msg2[64] = {
              0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,
              0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,
              0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,
              0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64
          };
          int MsgLen2 = 64;
          unsigned char MsgHash2[32] = {0};
          unsigned char StdHash2[32] = {
              0xde,0xbe,0x9f,0xf9,0x22,0x75,0xb8,0xa1,0x38,0x60,0x48,0x89,0xc1,0x8e,0x5a,0x4d,
              0x6f,0xdb,0x70,0xe5,0x38,0x7e,0x57,0x65,0x29,0x3d,0xcb,0xa3,0x9c,0x0c,0x57,0x32
          };
          
          // 計算 "20231302邱之釗" 的哈希值
          SM3_256(Msg1, MsgLen1, MsgHash1);
          
          printf("SM3 hash of '20231302邱之釗': ");
          for(int i = 0; i < 32; i++){
              printf("%02x", MsgHash1[i]);
          }
          printf("\n");
          
          // 可選:計算第二個測試用例
          SM3_256(Msg2, MsgLen2, MsgHash2);
          
          // 由于我們沒有 "20231302邱之釗" 的標準哈希值,這里只驗證第二個測試用例
          b = memcmp(MsgHash2, StdHash2, SM3_len/8);
          
          // 如果第二個測試用例通過,就返回0(成功)
          if (b == 0)
          {
              return 0;
          }
          else
          {
              return 1;
          }
      }
      int main(){
          printf("%d\n",SM3_SelfTest());
          return 0;
      }
      

      我的命令:

      qzz@qzz-virtual-machine:~/Desktop/sy2/sm3$ vi sm3.c
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm3$ vi sm3.c
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm3$ gcc -o sm3 sm3.c
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm3$ ./sm3
      SM3 hash of '20231302邱之釗': ab3b4e68cfc076f2c08df9a44f32077d618014aafafffe650f2bbc9c970b51fe
      0
      
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ vi sm4.h
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ gcc -o sm4 sm4.c
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ ./sm4
      Self-check successqzz@qzz-virtual-machine:~/Desktop/sy2/sm4$
      

      使用GmSSL命令驗證代碼正確性。和SM3代碼運行結果完全一致:

      qzz@qzz-virtual-machine:~/Desktop/sy2/sm3$ echo -n "20231302邱之釗" | gmssl sm3
      ab3b4e68cfc076f2c08df9a44f32077d618014aafafffe650f2bbc9c970b51fe
      

      屏幕截圖 2025-10-26 193326

      (三)SM4的實踐

      sm4.h

      #include<stdio.h> 
       
      //rotate n bits to the left in a 32bit buffer 
      #define SM4_Rotl32(buf, n) (((buf)<<n)|((buf)>>(32-n))) 
       
      unsigned int SM4_CK[32] ={0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 
       0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 
       0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 
       0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 
       0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 
       0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 
       0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 
       0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279}; 
       
      unsigned char SM4_Sbox[256] = 
       
      {0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05, 
       
      0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99, 
       
      0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,  
      0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6, 
       
      0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8, 
       
      0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35, 
       
      0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87, 
       
      0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e, 
       
      0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1, 
       
      0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3, 
       
      0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f, 
       
      0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51, 
       
      0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8, 
       
      0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0, 
       
      0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84, 
       
      0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48}; 
       
      unsigned int SM4_FK[4] = {0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC}; 
       
       
      /************************************************************ 
      Function: 
       void SM4_KeySchedule(unsigned char MK[], unsigned int rk[]); 
      Description: 
       Generate round keys 
      Calls: 
      Called By: 
       SM4_Encrypt; 
       SM4_Decrypt; 
      Input: 
       MK[]: Master key 
      Output: 
       rk[]: round keys 
      Return:null Others: 
      ************************************************************/ 
      void SM4_KeySchedule(unsigned char MK[], unsigned int rk[]); 
       
       
      /************************************************************ 
      Function: 
       void SM4_Encrypt(unsigned char MK[],unsigned char PlainText[],unsigned char 
      CipherText[]); 
      Description: 
       Encryption function 
      Calls: 
       SM4_KeySchedule 
      Called By: 
      Input: 
       MK[]: Master key 
       PlainText[]: input text 
      Output: 
       CipherText[]: output text 
      Return:null 
      Others: 
      ************************************************************/ 
      void SM4_Encrypt(unsigned char MK[],unsigned char PlainText[],unsigned char CipherText[]); 
       
       
      /************************************************************ 
      Function: 
       void SM4_Decrypt(unsigned char MK[],unsigned char CipherText[], unsigned char PlainText[]); 
      Description: 
       Decryption function 
      Calls: 
       SM4_KeySchedule 
      Called By: 
      Input: 
       MK[]: Master key 
       CipherText[]: input text 
      Output: 
       PlainText[]: output text 
      Return:null 
      Others: 
      ************************************************************/ 
      void SM4_Decrypt(unsigned char MK[],unsigned char CipherText[], unsigned char PlainText[]); 
       
       /************************************************************ 
      Function: 
       int SM4_SelfCheck() 
      Description: 
       Self-check with standard data 
      Calls: 
       SM4_Encrypt; 
       SM4_Decrypt; 
      Called By: 
      Input: 
      Output: 
      Return: 
       1 fail ; 0 success 
      Others: 
      ************************************************************/ 
      int SM4_SelfCheck(); 
      

      sm4.c

      //
      // Created by He-Zh on 2024/10/27.
      //
      
      #include "sm4.h"
      void SM4_KeySchedule(unsigned char MK[],unsigned int rk[])
      {
          unsigned int tmp,buf,K[36];
          int i;
          for(i=0;i<4;i++)
          {
              K[i]=SM4_FK[i]^( (MK[4*i]<<24) | (MK[4*i+1]<<16)
                               |(MK[4*i+2]<<8) | (MK[4*i+3]) );
          }
          for(i=0;i<32;i++)
          {
              tmp =K[i+1]^K[i+2]^K[i+3]^ SM4_CK[i];
              //nonlinear operation
              buf= (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24
                   |(SM4_Sbox[(tmp >> 16) & 0xFF]) << 16
                   |(SM4_Sbox[(tmp >> 8) & 0xFF]) << 8
                   |(SM4_Sbox[tmp & 0xFF]);
      //linear operation
              K[i+4]=K[i]^((buf)^(SM4_Rotl32((buf),13))^(SM4_Rotl32((buf),23)));
              rk[i]=K[i+4];
          }
      }
      void SM4_Encrypt(unsigned char MK[],unsigned char PlainText[],unsigned char CipherText[])
      {
          unsigned int rk[32],X[36],tmp,buf;
          int i,j;
          SM4_KeySchedule(MK,rk);
          for(j=0;j<4;j++)
          {
              X[j]=(PlainText[j*4]<<24) |(PlainText[j*4+1]<<16)
                   |(PlainText[j*4+2]<<8)|(PlainText[j*4+3]);
          }
          for(i=0;i<32;i++)
          {
              tmp = X[i+1]^X[i+2]^X[i+3]^rk[i];
              //nonlinear operation
              buf= ( SM4_Sbox[(tmp >> 24) & 0xFF]) << 24
                   |(SM4_Sbox[(tmp >> 16) & 0xFF]) << 16
                   |(SM4_Sbox[(tmp >> 8) & 0xFF]) << 8
                   |(SM4_Sbox[tmp & 0xFF]);
              //linear operation
              X[i+4]=X[i]^(buf^SM4_Rotl32((buf),2)^ SM4_Rotl32((buf),10)
                           ^ SM4_Rotl32((buf),18)^ SM4_Rotl32((buf),24));
          }
          for(j=0;j<4;j++)
          {
              CipherText[4*j]=(X[35-j]>> 24)& 0xFF;
              CipherText[4*j+1]=(X[35-j]>> 16)& 0xFF;
              CipherText[4*j+2]=(X[35-j]>> 8)& 0xFF;
              CipherText[4*j+3]=(X[35-j])& 0xFF;
          }
      }
      void SM4_Decrypt(unsigned char MK[],unsigned char CipherText[],unsigned char PlainText[])
      {
          unsigned int rk[32],X[36],tmp,buf;
          int i,j;
          SM4_KeySchedule(MK,rk);
          for(j=0;j<4;j++)
          {
              X[j]=(CipherText[j*4]<<24) |(CipherText[j*4+1]<<16)|
                   (CipherText[j*4+2]<<8)|(CipherText[j*4+3]);
          }
          for(i=0;i<32;i++)
          {
              tmp = X[i+1]^X[i+2]^X[i+3]^rk[31-i];
              //nonlinear operation
              buf= (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24
                   |(SM4_Sbox[(tmp >> 16) & 0xFF]) << 16
                   |(SM4_Sbox[(tmp >> 8) & 0xFF]) << 8
                   |(SM4_Sbox[tmp & 0xFF]);
              //linear operation
              X[i+4]=X[i]^(buf^SM4_Rotl32((buf),2)^ SM4_Rotl32((buf),10)
                           ^ SM4_Rotl32((buf),18)^ SM4_Rotl32((buf),24));
          }
          for(j=0;j<4;j++)
          {
              PlainText[4*j]=(X[35-j]>> 24)& 0xFF;
              PlainText[4*j+1]=(X[35-j]>>16)& 0xFF;
              PlainText[4*j+2]=(X[35-j]>> 8)& 0xFF;
              PlainText[4*j+3]=(X[35-j])& 0xFF;
          }
      }
      int SM4_SelfCheck()
      {
          int i;
          //Standard data
          unsigned char key[16] =
                  {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
          unsigned char plain[16]=
                  {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
          unsigned char
                  cipher[16]={0x68,0x1e,0xdf,0x34,0xd2,0x06,0x96,0x5e,0x86,0xb3,0xe9,0x4f,0x53,0x6e,0x42,0x46}
          ;
          unsigned char En_output[16];
          unsigned char De_output[16];
          SM4_Encrypt(key,plain,En_output);
          SM4_Decrypt(key,cipher,De_output);
          for(i=0;i<16;i++)
          {
              if ( (En_output[i]!=cipher[i]) | (De_output[i]!=plain[i]) )
              {
                   printf("Self-check error");
                  return 1;
              }
          }
          printf("Self-check success");
          return 0;
      }
      int main(){
          SM4_SelfCheck();
          return 0;
      }
      

      我的運行:

      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ vi sm4.h
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ vi sm4.c
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ gcc -o sm4 sm4.c
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ ./sm4
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ ./sm4
      Self-check successqzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ 
      

      使用GmSSL命令驗證代碼正確性。使用相同明文和密鑰進行加密所得到的結果和SM4代碼中的運行結果完全一致:

      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ echo -ne "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10" > key.binx32\x10" > key.bin
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ echo -ne "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10" > plain.txt 
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ gmssl sm4_ecb -encrypt -in plain.txt -key $(xxd -p -c 32 key.bin) -out enc.bin
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ od -tc -tx1 enc.bin 
      0000000   h 036 337   4 322 006 226   ^ 206 263 351   O   S   n   B   F
               68  1e  df  34  d2  06  96  5e  86  b3  e9  4f  53  6e  42  46
      0000020
      

      gmssl命令得出的結果是681edf34d206965e86b3e94f536e4246:
      屏幕截圖 2025-10-26 193952

      在 SM4_SelfCheck() 函數中,預期結果為681edf34d206965e86b3e94f536e4246,又因為運行函數結果顯示運行結果與預期一致,故gmssl命令結果驗證得到sm4代碼結果正確:
      image

      在密標委?站http://www.gmbz.org.cn/main/bzlb.html查找SM2,SM3,SM4相關標準,分析代碼實現與標準的對應關系。(6分)

      SM2加解密

      標準 函數實現 備注
      常數與符號 一一對應
      輔助函數 KDF
      加密算法 SM2_Encrypt 函數
      解密算法 SM2_Decrypt 函數
      橢圓曲線系統參數 SM2_Init 函數
      用戶密鑰對 Test_PubKey 函數,SM2_KeyGeneration 函數 SM2_KeyGeneration 函數作用:該函數用于從給定的私鑰生成相應的公鑰。在橢圓曲線密碼學中,公鑰是通過對基點(G)進行私鑰的標量乘法得到的。即公鑰 pubKey = [priKey]G,其中 priKey 是私鑰,G 是橢圓曲線上的基點,[priKey]G 表示將基點G進行私鑰對應的標量乘法操作。輸入:私鑰 priKey,這是一個大整數,通常在 [1, n-2] 范圍內,其中n是橢圓曲線的基點G的階。輸出:公鑰 pubKey,這是一個橢圓曲線上的點,表示為 (x, y) 坐標。返回:函數返回0表示成功生成公鑰,返回1表示生成公鑰過程中出現錯誤,比如私鑰不在有效范圍內或者公鑰點不在橢圓曲線上。Test_PubKey 函數作用:該函數用于驗證給定的公鑰是否有效。有效性檢查包括:公鑰點是否在無窮遠點(點在橢圓曲線上的定義之外),公鑰點的坐標是否在有限域內,以及公鑰點是否在橢圓曲線上,最后還要檢查公鑰點的階是否等于n。輸入:公鑰點 pubKey,這是一個橢圓曲線上的點。輸出:無。返回:函數返回0表示公鑰有效,返回1表示公鑰點是無窮遠點,返回2表示公鑰點的X或Y坐標超出了有限域的范圍,返回3表示公鑰點不在橢圓曲線上,返回4表示公鑰點的階不等于n。

      SM2密鑰協商

      標準 函數實現 備注
      常數與符號 一一對應
      輔助函數 KDF
      用戶密鑰對 SM2_KeyGeneration 函數
      密鑰交換協議 SM2_KeyEx_Init_I 函數,SM2_KeyEx_Re_I 函數,SM2_KeyEx_Init_II 函數,SM2_KeyEx_Re_II 函數 SM2_KeyEx_Init_I 函數:作用:密鑰交換的初始化步驟,由發起方(例如Alice)生成一個隨機數rA并計算點RA,這是密鑰交換的第一步。SM2_KeyEx_Re_I 函數:作用:密鑰交換的響應步驟,由響應方(例如Bob)生成RB,并計算一個共享的秘密密鑰。Bob將RB發送給Alice。SM2_KeyEx_Init_II 函數:作用:密鑰交換的完成步驟,由發起方Alice計算共享的秘密密鑰,并計算一個哈希值供響應方Bob驗證。SM2_KeyEx_Re_II 函數: 作用:(可選)響應方Bob驗證從發起方Alice接收到的哈希值,以確保密鑰交換的完整性和安全性

      SM2簽名驗簽

      標準 函數實現 備注
      常數與符號 一一對應
      輔助函數 KDF
      用戶密鑰對 SM2_KeyGeneration
      數字簽名生成算法 SM2_Sign
      數字簽名驗證算法 SM2_Verify
      其他 SM2_Init、Test_Point、Test_PubKey、Test_Zero、Test_n、Test_Range和SM3_256 持上述簽名生成和驗證過程中的輔助函數。它們用于初始化曲線參數、驗證點是否在曲線上、驗證公鑰的有效性、檢查大整數是否為零或等于n、以及計算哈希值

      SM3

      標準 函數實現 詳細解釋
      常數 一一對應
      消息擴展 BiToW 函數,WToW1 函數 BiToW 函數:這個函數將輸入的512位消息塊(分割成16個32位字)擴展到一個512位的W數組,分成68個32位字。這個過程涉及到位操作和與SM3算法的固定參數相結合。WToW1 函數:這個函數進一步擴展消息,通過將W數組的每個元素與其后第四個元素進行異或操作,生成新的W1數組。這個數組將用于后續的壓縮函數。
      壓縮函數 CF 函數,SM3_compress 函數 CF 函數:這個函數執行SM3算法的核心壓縮操作,它使用W和W1數組以及一系列非線性和線性變換來更新哈希值。這個過程涉及到多輪迭代,每輪使用不同的參數和操作。SM3_compress 函數:這個函數執行實際的壓縮操作,它調用BigEndian函數進行字節序轉換,然后調用BiToW和WToW1函數進行消息擴展,最后調用CF函數執行壓縮操作。
      迭代過程 CF 函數,SM3_compress 函數 在CF函數中:這個函數通過64輪迭代,使用W和W1數組以及一系列非線性和線性變換來更新哈希值。每輪迭代都涉及到消息的加權、壓縮和哈希狀態的更新。在SM3_process函數中:這個函數處理輸入的消息,將其分割成512位的塊,并重復調用SM3_compress函數來壓縮每個塊,直到所有消息都被處理。

      SM4

      標準 函數實現
      輪函數F SM4_KeySchedule 函數
      加密算法 SM4_Encrypt 函數
      解密算法 SM4_Decrypt 函數
      密鑰擴展算法 SM4_KeySchedule 函數

      3.使用Rust完成SM2,SM3,SM4算法的實現(選做,10分)

      (一)SM3
      sm3.rs

      use std::mem::transmute;
      
      const SM3_LEN: usize = 256;
      const SM3_T1: u32 = 0x79CC4519;
      const SM3_T2: u32 = 0x7A879D8A;
      const SM3_IVA: u32 = 0x7380166f;
      const SM3_IVB: u32 = 0x4914b2b9;
      const SM3_IVC: u32 = 0x172442d7;
      const SM3_IVD: u32 = 0xda8a0600;
      const SM3_IVE: u32 = 0xa96f30bc;
      const SM3_IVF: u32 = 0x163138aa;
      const SM3_IVG: u32 = 0xe38dee4d;
      const SM3_IVH: u32 = 0xb0fb0e4e;
      
      #[derive(Clone)]
      struct Sm3State {
          state: [u32; 8],
          length: u64,
          curlen: usize,
          buf: [u8; 64],
      }
      
      impl Sm3State {
          fn new() -> Self {
              Self {
                  state: [SM3_IVA, SM3_IVB, SM3_IVC, SM3_IVD, SM3_IVE, SM3_IVF, SM3_IVG, SM3_IVH],
                  length: 0,
                  curlen: 0,
                  buf: [0u8; 64],
              }
          }
      
          fn p1(x: u32) -> u32 {
              x ^ Sm3State::rotl(x, 15) ^ Sm3State::rotl(x, 23)
          }
      
          fn p0(x: u32) -> u32 {
              x ^ Sm3State::rotl(x, 9) ^ Sm3State::rotl(x, 17)
          }
      
          fn ff0(a: u32, b: u32, c: u32) -> u32 {
              a ^ b ^ c
          }
      
          fn ff1(a: u32, b: u32, c: u32) -> u32 {
              (a & b) | (a & c) | (b & c)
          }
      
          fn gg0(e: u32, f: u32, g: u32) -> u32 {
              e ^ f ^ g
          }
      
          fn gg1(e: u32, f: u32, g: u32) -> u32 {
              (e & f) | (!e & g)
          }
      
          fn rotl(x: u32, n: u32) -> u32 {
              (x << n) | (x >> (32 - n))
          }
      
          fn big_endian(src: &[u8], bytelen: usize, des: &mut [u8]) {
              for i in 0..(bytelen / 4) {
                  des[4 * i] = src[4 * i + 3];
                  des[4 * i + 1] = src[4 * i + 2];
                  des[4 * i + 2] = src[4 * i + 1];
                  des[4 * i + 3] = src[4 * i];
              }
          }
      
          fn bi_to_w(bi: &[u32; 16], w: &mut [u32; 68]) {
              w[0..16].copy_from_slice(bi);
              for i in 16..68 {
                  let tmp = w[i - 16] ^ w[i - 9] ^ Sm3State::rotl(w[i - 3], 15);
                  w[i] = Sm3State::p1(tmp) ^ Sm3State::rotl(w[i - 13], 7) ^ w[i - 6];
              }
          }
      
          fn w_to_w1(w: &[u32; 68], w1: &mut [u32; 64]) {
              for i in 0..64 {
                  w1[i] = w[i] ^ w[i + 4];
              }
          }
      
          fn cf(w: &[u32; 68], w1: &[u32; 64], v: &mut [u32; 8]) {
              let mut a = v[0];
              let mut b = v[1];
              let mut c = v[2];
              let mut d = v[3];
              let mut e = v[4];
              let mut f = v[5];
              let mut g = v[6];
              let mut h = v[7];
              let mut t = SM3_T1;
      
              for j in 0..64 {
                  if j == 16 {
                      t = Sm3State::rotl(SM3_T2, 16);
                  } else if j > 0 {
                      t = Sm3State::rotl(t, 1);
                  }
                  let ss1 = Sm3State::rotl(Sm3State::rotl(a, 12).wrapping_add(e).wrapping_add(t), 7);
                  let ss2 = ss1 ^ Sm3State::rotl(a, 12);
                  let tt1 = if j <= 15 {
                      Sm3State::ff0(a, b, c)
                  } else {
                      Sm3State::ff1(a, b, c)
                  }
                      .wrapping_add(d)
                      .wrapping_add(ss2)
                      .wrapping_add(w1[j]);
                  let tt2 = if j <= 15 {
                      Sm3State::gg0(e, f, g)
                  } else {
                      Sm3State::gg1(e, f, g)
                  }
                      .wrapping_add(h)
                      .wrapping_add(ss1)
                      .wrapping_add(w[j]);
      
                  d = c;
                  c = Sm3State::rotl(b, 9);
                  b = a;
                  a = tt1;
                  h = g;
                  g = Sm3State::rotl(f, 19);
                  f = e;
                  e = Sm3State::p0(tt2);
              }
      
              v[0] ^= a;
              v[1] ^= b;
              v[2] ^= c;
              v[3] ^= d;
              v[4] ^= e;
              v[5] ^= f;
              v[6] ^= g;
              v[7] ^= h;
          }
      
          fn compress(&mut self) {
              let mut w = [0u32; 68];
              let mut w1 = [0u32; 64];
              let mut buf = [0u32; 16];
      
              for i in 0..16 {
                  buf[i] = u32::from_be_bytes([self.buf[4 * i], self.buf[4 * i + 1], self.buf[4 * i + 2], self.buf[4 * i + 3]]);
              }
      
              Sm3State::bi_to_w(&buf, &mut w);
              Sm3State::w_to_w1(&w, &mut w1);
              Sm3State::cf(&w, &w1, &mut self.state);
          }
      
          fn process(&mut self, buf: &[u8]) {
              for &b in buf {
                  self.buf[self.curlen] = b;
                  self.curlen += 1;
      
                  if self.curlen == 64 {
                      self.compress();
                      self.length += 512;
                      self.curlen = 0;
                  }
              }
          }
      
          fn done(&mut self, hash: &mut [u8; 32]) {
              self.length += (self.curlen as u64) << 3;
      
              self.buf[self.curlen] = 0x80;
              self.curlen += 1;
      
              if self.curlen > 56 {
                  self.buf[self.curlen..64].fill(0);
                  self.compress();
                  self.curlen = 0;
              }
      
              self.buf[self.curlen..56].fill(0);
      
              self.buf[56..64].copy_from_slice(&self.length.to_be_bytes());
              self.compress();
      
              for (i, &s) in self.state.iter().enumerate() {
                  hash[i * 4..i * 4 + 4].copy_from_slice(&s.to_be_bytes());
              }
          }
      }
      
      fn sm3_256(buf: &[u8], hash: &mut [u8; 32]) {
          let mut state = Sm3State::new();
          state.process(buf);
          state.done(hash);
      }
      
      fn main() {
          let mut hash = [0u8; 32];
          sm3_256(b"abc", &mut hash);
          for byte in &hash {
              print!("{:02x}", byte);
          }
          println!();
      }
      

      運行結果:

      qzz@qzz-virtual-machine:~/Desktop/sy2/sm3$ rustc sm3.rs
      warning: unused import: `std::mem::transmute`
       --> sm3.rs:1:5
        |
      1 | use std::mem::transmute;
        |     ^^^^^^^^^^^^^^^^^^^
        |
        = note: `#[warn(unused_imports)]` on by default
      
      warning: constant `SM3_LEN` is never used
       --> sm3.rs:3:7
        |
      3 | const SM3_LEN: usize = 256;
        |       ^^^^^^^
        |
        = note: `#[warn(dead_code)]` on by default
      
      warning: associated function `big_endian` is never used
        --> sm3.rs:61:8
         |
      23 | impl Sm3State {
         | ------------- associated function in this implementation
      ...
      61 |     fn big_endian(src: &[u8], bytelen: usize, des: &mut [u8]) {
         |        ^^^^^^^^^^
      
      warning: 3 warnings emitted
      
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm3$ ./sm3
      66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm3$ 
      

      image
      (二)SM4
      sm4.rs

      const SM4_CK: [u32; 32] = [
          0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
          0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
          0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
          0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
          0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
          0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
          0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
          0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279,
      ];
      
      const SM4_SBOX: [u8; 256] = [
          0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
          0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
          0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
          0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
          0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
          0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
          0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
          0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
          0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
          0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
          0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
          0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
          0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
          0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
          0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
          0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
      ];
      
      const SM4_FK: [u32; 4] = [0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC];
      
      fn sm4_rotl32(buf: u32, n: u32) -> u32 {
          (buf << n) | (buf >> (32 - n))
      }
      
      fn sm4_key_schedule(mk: &[u8], rk: &mut [u32; 32]) {
          let mut k = [0u32; 36];
          for i in 0..4 {
              k[i] = SM4_FK[i]
                  ^ ((mk[4 * i] as u32) << 24
                  | (mk[4 * i + 1] as u32) << 16
                  | (mk[4 * i + 2] as u32) << 8
                  | (mk[4 * i + 3] as u32));
          }
      
          for i in 0..32 {
              let tmp = k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ SM4_CK[i];
              let buf = (SM4_SBOX[(tmp >> 24) as usize & 0xFF] as u32) << 24
                  | (SM4_SBOX[(tmp >> 16) as usize & 0xFF] as u32) << 16
                  | (SM4_SBOX[(tmp >> 8) as usize & 0xFF] as u32) << 8
                  | SM4_SBOX[tmp as usize & 0xFF] as u32;
              k[i + 4] = k[i] ^ (buf ^ sm4_rotl32(buf, 13) ^ sm4_rotl32(buf, 23));
              rk[i] = k[i + 4];
          }
      }
      fn sm4_substitute(input: u32) -> u32 {
          // 使用S盒來替代輸入字節
          let mut buf = 0u32;
          buf |= (SM4_SBOX[(input >> 24) as usize & 0xFF] as u32) << 24;
          buf |= (SM4_SBOX[(input >> 16) as usize & 0xFF] as u32) << 16;
          buf |= (SM4_SBOX[(input >> 8) as usize & 0xFF] as u32) << 8;
          buf |= SM4_SBOX[input as usize & 0xFF] as u32;
          buf
      }
      
      fn sm4_round_function(x0: u32, x1: u32, x2: u32, x3: u32, rk: u32) -> u32 {
          let tmp = x1 ^ x2 ^ x3 ^ rk;
          let buf = sm4_substitute(tmp);
          x0 ^ buf ^ sm4_rotl32(buf, 2) ^ sm4_rotl32(buf, 10) ^ sm4_rotl32(buf, 18) ^ sm4_rotl32(buf, 24)
      }
      
      fn sm4_encrypt(input: &[u8], output: &mut [u8], rk: &[u32; 32]) {
          let mut x = [0u32; 36];
          for i in 0..4 {
              x[i] = (input[4 * i] as u32) << 24
                  | (input[4 * i + 1] as u32) << 16
                  | (input[4 * i + 2] as u32) << 8
                  | input[4 * i + 3] as u32;
          }
      
          for i in 0..32 {
              x[i + 4] = sm4_round_function(x[i], x[i + 1], x[i + 2], x[i + 3], rk[i]);
          }
      
          for i in 0..4 {
              output[4 * i] = (x[35 - i] >> 24) as u8;
              output[4 * i + 1] = (x[35 - i] >> 16) as u8;
              output[4 * i + 2] = (x[35 - i] >> 8) as u8;
              output[4 * i + 3] = x[35 - i] as u8;
          }
      }
      
      fn sm4_decrypt(input: &[u8], output: &mut [u8], rk: &[u32; 32]) {
          let mut x = [0u32; 36];
          for i in 0..4 {
              x[i] = (input[4 * i] as u32) << 24
                  | (input[4 * i + 1] as u32) << 16
                  | (input[4 * i + 2] as u32) << 8
                  | input[4 * i + 3] as u32;
          }
      
          for i in 0..32 {
              x[i + 4] = sm4_round_function(x[i], x[i + 1], x[i + 2], x[i + 3], rk[31 - i]);
          }
      
          for i in 0..4 {
              output[4 * i] = (x[35 - i] >> 24) as u8;
              output[4 * i + 1] = (x[35 - i] >> 16) as u8;
              output[4 * i + 2] = (x[35 - i] >> 8) as u8;
              output[4 * i + 3] = x[35 - i] as u8;
          }
      }
      fn sm4_self_check() -> bool {
          // 標準測試數據
          let key: [u8; 16] = [
              0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
              0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
          ];
          let plain: [u8; 16] = [
              0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
              0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
          ];
          let expected_cipher: [u8; 16] = [
              0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e,
              0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46,
          ];
      
          // 結果緩沖區
          let mut rk = [0u32; 32];
          let mut cipher = [0u8; 16];
          let mut decrypted = [0u8; 16];
      
          // 生成輪密鑰
          sm4_key_schedule(&key, &mut rk);
      
          // 加密
          sm4_encrypt(&plain, &mut cipher, &rk);
          // 檢查加密結果是否與期望值相同
          if cipher != expected_cipher {
              println!("Self-check error: encryption failed.");
              return false;
          }
      
          // 解密
          sm4_decrypt(&cipher, &mut decrypted, &rk);
          // 檢查解密結果是否恢復為原始明文
          if decrypted != plain {
              println!("Self-check error: decryption failed.");
              return false;
          }
      
          println!("Self-check success.");
          true
      }
      
      fn main() {
          if sm4_self_check() {
              println!("SM4 encryption and decryption passed the self-check.");
          } else {
              println!("SM4 encryption and decryption failed the self-check.");
          }
      }
      

      運行結果

      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ vi sm4.rs
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ rustc sm4.rs
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ ./sm4
      Self-check success.
      SM4 encryption and decryption passed the self-check.
      qzz@qzz-virtual-machine:~/Desktop/sy2/sm4$ 
      

      image

      代碼,文檔托管到gitee或github等,推薦gitclone

      https://gitee.com/q9z2z2/922.git

      posted @ 2025-11-02 17:39  20231302邱之釗  閱讀(11)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩精品一区二区三区激情| 天天摸夜夜摸夜夜狠狠添| 日韩深夜免费在线观看| 成人婷婷网色偷偷亚洲男人的天堂| 久久一级精品久熟女人妻| 在线看av一区二区三区| 日本道之久夂综合久久爱| 国内精品伊人久久久久影院对白| 日韩乱码人妻无码中文字幕视频| 亚洲另类激情专区小说婷婷久| 亚洲av无码牛牛影视在线二区| 国产精品VA尤物在线观看| 女人被狂c躁到高潮视频 | 亚洲区成人综合一区二区| 国产精品中文字幕在线看| 人妻一区二区三区三区| 红桃视频成人传媒| 激情五月日韩中文字幕| 国产成人久久精品二区三| 亚洲综合一区二区国产精品| 日韩V欧美V中文在线| 亚洲精品自拍视频在线看| 操操操综合网| 精品人妻一区二区三区蜜臀| 成人国产精品三上悠亚久久| 国产亚洲精品久久久久久大师| 亚洲欧洲精品一区二区| 中文字幕无码免费不卡视频| 日韩精品成人网页视频在线| 国产成人毛片无码视频软件| 免费特黄夫妻生活片| 国产亚洲无日韩乱码| 亚洲精品二区在线播放| 日本一道一区二区视频| 激情综合五月| 亚洲夜夜欢一区二区三区| 精品国产一区av天美传媒| 免费极品av一视觉盛宴| 在线免费成人亚洲av| 成年女人午夜毛片免费视频| 欧美性潮喷xxxxx免费视频看|