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邱之钊  阅读(28)  评论(0)    收藏  举报