February 3, 2022

SM4-P.Z

先贴个我手打的源码

SM4

SM4.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#ifndef SM4_H
#define SM4_H

#define ENC 1
#define DEC 0

/**
* 模式与密钥
*/
typedef struct
{
int mode;
unsigned long sk[32];
} Context;

/**
* 参数 ctx: 代初始化的结构体
* 参数 key: 16字节密钥
*/
void SetKeyEnc(Context * ctx, unsigned char key[16]);

/**
* 参数 ctx: 代初始化的结构体
* 参数 key: 16字节密钥
*/
void SetKeyDec(Context * ctx, unsigned char key[16]);

/**
* 参数 ctx: 结构体
* 参数 mode: 解密或解密模式
* 参数 len: input的长度
* 参数 input: 明文字符串
* 参数 output: 加密后字符串
*/
void CryptEBC(Context * ctx, int mode, int len, unsigned char * input, unsigned char * output);

#endif

SM4.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#include <stdio.h>
#include <string.h>
#include "SM4.h"

/**
* 作用: 无符号长整型数组 转 无符号长整型
*/
#define GET_ULONG(n, b, i) \
(n) = ( (unsigned long) (b)[(i )] << 24 ) \
| ( (unsigned long) (b)[(i + 1)] << 16 ) \
| ( (unsigned long) (b)[(i + 2)] << 8 ) \
| ( (unsigned long) (b)[(i + 3)] ); \

/**
* 作用: 无符号长整型 转 无符号长整型数组
*/
#define PUT_ULONG(n, b, i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}

/**
* 作用: 参数 x 左移参数 n 位
*/
#define SHL(x, n) ( ((x) & 0xFFFFFFFF) << n )

/**
* 作用: 参数 x 逻辑左移参数 n 位
*/
#define ROTL(x, n) ( SHL((x), n) | ((x) >> (32 - n)) )

/**
* 作用: 两个参数交换
*/
#define SWAP(a, b) { unsigned t = a; a = b; b = t; t = 0; }

/**
* S盒
*/
static const unsigned char Sbox[16][16] =
{
{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}
};

/**
* 密钥用常量
*/
static const unsigned long FK[4] = {0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc};

/**
* 密钥用常量
*/
static const unsigned long 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
};

/**
* 作用: S盒字节代换
*/
static unsigned char SubByte(unsigned char num)
{
unsigned char * ps = (unsigned char *) Sbox; //获取数组指针 就可以一维数组访问
unsigned char retval = (unsigned char) (ps[num]);

return retval;
}

/**
* 作用: 参数ka 字节代换 + 线性运算
*/
static unsigned long T(unsigned long ka)
{
unsigned long bb = 0;
unsigned long retval = 0;
unsigned char a[4];
unsigned char b[4];

PUT_ULONG(ka, a, 0); //ka放到数组a
for ( int i = 0; i < 4; i++ )
b[i] = SubByte(a[i]); //逐个字节代换到b
GET_ULONG(bb, b, 0);
retval = bb ^ ( ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24) ); //最后线性运算

return retval;
}

/**
* 参数 x0 x1 x2 x3: 原生数
* 参数 rk: 密钥
*/
static unsigned long F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk)
{
return (x0 ^ T(x1 ^ x2 ^ x3 ^ rk));
}

/**
* 作用: 密钥扩展中的一轮
*/
static unsigned long CalcRoundKey(unsigned long ka)
{
unsigned long bb = 0;
unsigned long retval = 0;
unsigned char a[4];
unsigned char b[4];

PUT_ULONG(ka, a, 0);
for ( int i = 0; i < 4; i++ )
b[i] = SubByte(a[i]);
GET_ULONG(bb, b, 0);
retval = bb ^ (ROTL(bb, 13) ^ ROTL(bb, 23));

return retval;
}

/**
* 参数 SK: 密钥存放
* 参数 key: 密钥
*/
static void SetKey(unsigned long SK[32], unsigned char key[16])
{
unsigned long MK[4];
unsigned long k[36];

GET_ULONG(MK[0], key, 0);
GET_ULONG(MK[1], key, 4);
GET_ULONG(MK[2], key, 8);
GET_ULONG(MK[3], key, 12);
k[0] = MK[0] ^ FK[0];
k[1] = MK[1] ^ FK[1];
k[2] = MK[2] ^ FK[2];
k[3] = MK[3] ^ FK[3];
for ( int i = 0; i < 32; i++ )
{
k[i + 4] = k[i] ^ (CalcRoundKey(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i]));
SK[i] = k[i + 4];
// printf("0x%X, ", SK[i]);
}
}

/**
* 作用: 标准SM4一轮加密
* 参数 sk: 已初始化密钥
* 参数 input: 明文字符串
* 参数 output: 输入密文字符串
*/
static void Round(unsigned long sk[32], unsigned char input[16], unsigned char output[16])
{
unsigned long tmp[36] = { 0 };

GET_ULONG(tmp[0], input, 0);
GET_ULONG(tmp[1], input, 4);
GET_ULONG(tmp[2], input, 8);
GET_ULONG(tmp[3], input, 12);
for ( int i = 0; i < 32; i++ )
tmp[i + 4] = F(tmp[i], tmp[i + 1], tmp[i + 2], tmp[i + 3], sk[i]);
PUT_ULONG(tmp[35], output, 0);
PUT_ULONG(tmp[34], output, 4);
PUT_ULONG(tmp[33], output, 8);
PUT_ULONG(tmp[32], output, 12);
}

/**
* 作用: 初始化加密密钥
*/
void SetKeyEnc(Context * ctx, unsigned char key[16])
{
ctx->mode = ENC;
SetKey(ctx->sk, key);
}

/**
* 作用: 初始化解密密钥
*/
void SetKeyDec(Context * ctx, unsigned char key[16])
{
ctx->mode = DEC;
SetKey(ctx->sk, key);
for ( int i = 0; i < 16; i++ )
SWAP(ctx->sk[i], ctx->sk[31 - i]);
}

/**
* 参数 ctx: 结构体
* 参数 mode: 解密或解密模式
* 参数 len: input的长度
* 参数 input: 明文字符串
* 参数 output: 加密后字符串
*/
void CryptEBC(Context * ctx, int mode, int len, unsigned char * input, unsigned char * output)
{
while ( len > 0)
{
Round(ctx->sk, input, output);

input += 16;
output += 16;
len -= 16;
}
}


//int main(void)
//{
// unsigned long test[] = { 1, 2, 3, 4 };
// unsigned long n = 0x01020304;
// unsigned long data[4] = { 0 };
//
// n = GET_ULONG(n, test, 0);
// printf("0x%X", n);
//
// puts("\n");
//
// PUT_ULONG(n, data, 0);
// printf("0x%X, 0x%X, 0x%X, 0x%X", data[0], data[1], data[2], data[3]);
//
// puts("\n");
//
// printf("0x%X", SubByte(0xFF));
//
// return 0;
//}

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
#include <string.h>
#include "SM4.h"

int main(void)
{
unsigned char key[16] =
{
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc,
0xba, 0x98, 0x76, 0x54, 0x32, 0x10
};
unsigned char input[16] =
{
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc,
0xba, 0x98, 0x76, 0x54, 0x32, 0x10
};
unsigned char output[16] =
{
0xBE, 0x04, 0x06, 0x80, 0xC5, 0xAF, 0x76, 0x47, 0x9F, 0xCC,
0x40, 0x1F, 0xD8, 0xBF, 0x92, 0xEF
};
Context ctx;
int i;

SetKeyEnc(&ctx, key);
CryptEBC(&ctx, 1, 16, input, output);
for ( i = 0; i < 16; i++ )
printf("0x%X, ", output[i]);

puts("\n");

SetKeyDec(&ctx, key);
CryptEBC(&ctx, 0, 16, output, output);
for ( i = 0; i < 16; i++ )
printf("0x%X, ", output[i]);

return 0;
}
DASCTF X SU
🍬
HFCTF2022
🍪

About this Post

This post is written by P.Z, licensed under CC BY-NC 4.0.