【无标题】

《密码系统设计》实验
实验项目

在 Ubuntu或openEuler中(推荐 openEuler)中调试运⾏商⽤密码检测中⼼https://www.scctc.org.cn/xzzx/sfydm/ydmxz/提供的源代码,⾄少运⾏SM2,SM3,SM4代码。使⽤GmSSL命令验证你代码的正确性。使⽤Markdown记录详细记录实践过程,每完成⼀项功能或者⼀个函数git commit ⼀次。(14分)
SM3

#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) (xSM3_rotl32(x,15)SM3_rotl32(x,23))
#define SM3_p0(x) (xSM3_rotl32(x,9)SM3_rotl32(x,17))
#define SM3_ff0(a,b,c) (abc)
#define SM3_ff1(a,b,c) ((a&b)|(a&c)|(b&c))
#define SM3_gg0(e,f,g) (efg)
#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

#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(j0)
{
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[4i+3];
src[4
i+3] = tmp;
tmp = des[4i+1];
des[4
i+1] = src[4i+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;
unsigned char Msg1[3]={0x61,0x62,0x63};
int MsgLen1=3;
unsigned char MsgHash1[32]={0};
unsigned char
StdHash1[32]={0x66,0xC7,0xF0,0xF4,0x62,0xEE,0xED,0xD9,0xD1,0xF2,0xD4,0x6B,0xDC,0x10,0xE4,0xE2,
0x41,0x67,0xC4,0x87,0x5C,0xF2,0xF7,0xA2,0x29,0x7D,0xA0,0x2B,0x8F,0x4B,0xA8,0xE0};
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};
SM3_256(Msg1,MsgLen1,MsgHash1);
SM3_256(Msg2,MsgLen2,MsgHash2);
for(int i = 0; i < 32; i++){
printf(“%02x”, MsgHash1[i]);
}
printf(“\n”);
a=memcmp(MsgHash1,StdHash1,SM3_len/8);
b=memcmp(MsgHash2,StdHash2,SM3_len/8);
if ((a0) && (b0))
{
return 0;
}
else
{
return 1;
}
}
int main(){
printf(“%d\n”,SM3_SelfTest());
return 0;
}
运行结果
$ ./sm3
66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0
0
$ echo -n “abc” | gmssl sm3
66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0
自测中生成了"abc"的哈希值,使用gmssl验证通过

SM4
SM4.h
xxxxxxxxxx157 1//2// Created by He-Zh on 2024/10/27.3//45#ifndef EXP2_SM4_H6#define EXP2_SM4_H7#define SM4_Rotl32(buf, n) (((buf)<<n)|((buf)>>(32-n)))8#include<stdio.h>9unsigned int SM4_CK[32] ={0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,10 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,11 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,12 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,13 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,14 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,15 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,16 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279};17unsigned char SM4_Sbox[256] =1819 {0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,2021 0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,2223 0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,2425 0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,2627 0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,2829 0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,3031 0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,3233 0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,3435 0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,3637 0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,3839 0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,4041 0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,4243 0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,4445 0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,4647 0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,4849 0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48};50unsigned int SM4_FK[4] = {0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC};51void SM4_KeySchedule(unsigned char MK[], unsigned int rk[]);52void SM4_Encrypt(unsigned char MK[],unsigned char PlainText[],unsigned char CipherText[]);53void SM4_Decrypt(unsigned char MK[],unsigned char CipherText[], unsigned char PlainText[]);54int SM4_SelfCheck();5556#endif //EXP2_SM4_H57

SM4.c

#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[4i]<<24) | (MK[4i+1]<<16)
|(MK[4i+2]<<8) | (MK[4i+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[j4]<<24) |(PlainText[j4+1]<<16)
|(PlainText[j4+2]<<8)|(PlainText[j4+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](bufSM4_Rotl32((buf),2)^ SM4_Rotl32((buf),10)
^ SM4_Rotl32((buf),18)^ SM4_Rotl32((buf),24));
}
for(j=0;j<4;j++)
{
CipherText[4j]=(X[35-j]>> 24)& 0xFF;
CipherText[4
j+1]=(X[35-j]>> 16)& 0xFF;
CipherText[4j+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[j4]<<24) |(CipherText[j4+1]<<16)|
(CipherText[j4+2]<<8)|(CipherText[j4+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](bufSM4_Rotl32((buf),2)^ SM4_Rotl32((buf),10)
^ SM4_Rotl32((buf),18)^ SM4_Rotl32((buf),24));
}
for(j=0;j<4;j++)
{
PlainText[4j]=(X[35-j]>> 24)& 0xFF;
PlainText[4
j+1]=(X[35-j]>>16)& 0xFF;
PlainText[4j+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;
}
运行结果
$ echo -ne “\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10” > key.bin
$ echo -ne “\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10” > plain.txt
$ gmssl sm4_ecb -encrypt -in plain.txt -key $(xxd -p -c 32 key.bin) -out enc.bin
$ 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结果一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值