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
截圖如下:

(二)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

(三)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:

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

在密標委?站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$

(二)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$

浙公網安備 33010602011771號