常见加密解密编码算法
carbofish

常见的加密解密算法实现汇总

HEX

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
#include "stdio.h" // sprintf()函数声明所在的头文件
char data[] = "Hello World!!\r\n";
char res[32];

int str_2_hex_str(char *dest, char *src)
{
int len = strlen(src); // 获取接收数据长度
int i,j;
for (i = 0, j = 0; i < len; i++) {
sprintf(&dest[j], "%02X", src[i]);
j+=2; // 每个16进制占2个长度
}
dest[j] = '\0'; // 添加字符串结束符
return j; // 返回字符串长度
}

int len = str_2_hex_str(res, data);
///////////////////////////////
#include <stdlib.h> // 要使用strtol()库函数,需要包含头文件

char data[] = "48656C6C6F20576F726C6421210D0A"; // 假如,我们接收到这样的数据
char res[32]; // 储存转换后的结果

int hex_str_2_str(char *dest, char *src)
{
int len = strlen(src); // 获取接收数据长度
int i,j;
for (i = 0, j = 0; i < len; i+=2) { // 每次取两个字符
char tmp_buf[3]; // 每两个字符组成一个16进制字符串,同时结尾需要空字符来告诉编译器我们的是字符串
char *endptr; // 保存已转换数值后的下一个字符
// 以下为取待转换的16进制字符串
tmp_buf[0] = src[i];
tmp_buf[1] = src[i + 1];
tmp_buf[2] = '\0'; // 记得添加空字符
// 转换成16进制,base传16即可
dest[j++] = strtol(tmp_buf, &endptr, 16);
}
dest[j] = '\0'; // 添加字符串结束符
return j;
}

int len = hex_str_2_str(res, data);

BASE64

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
//base64加密
char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void encodeBase64(char* str,int len,char** in){

//读取3个字节zxc,转换为二进制01111010 01111000 01100011
//转换为4个6位字节,011110 100111 100001 100011
//不足8位在前补0,变成00011110 00100111 00100001 00100011
//若剩余的字节数不足以构成4个字节,补等号
int encodeStrLen = 1 + (len/3)*4 ,k=0;
encodeStrLen += len%3 ? 4 : 0;
char* encodeStr = (char*)(malloc(sizeof(char)*encodeStrLen));
for(int i=0;i<len;i++){
if(len - i >= 3){
encodeStr[k++] = base64[(unsigned char)str[i]>>2];
encodeStr[k++] = base64[((unsigned char)str[i]&0x03)<<4 | (unsigned char)str[++i]>>4];
encodeStr[k++] = base64[((unsigned char)str[i]&0x0f)<<2 | (unsigned char)str[++i]>>6];
encodeStr[k++] = base64[(unsigned char)str[i]&0x3f];
}else if(len-i == 2){
encodeStr[k++] = base64[(unsigned char)str[i] >> 2];
encodeStr[k++] = base64[((unsigned char)str[i]&0x03) << 4 | ((unsigned char)str[++i] >> 4)];
encodeStr[k++] = base64[((unsigned char)str[i]&0x0f) << 2];
encodeStr[k++] = '=';
}else{
encodeStr[k++] = base64[(unsigned char)str[i] >> 2];
encodeStr[k++] = base64[((unsigned char)str[i] & 0x03) << 4]; //末尾补两个等于号
encodeStr[k++] = '=';
encodeStr[k++] = '=';
}
}
encodeStr[k] = '\0';
*in = encodeStr;
}

/**
* 解码既编码的逆过程,先找出编码后的字符在编码之前代表的数字
* 编码中将3位个字符变成4个字符,得到这4个字符的每个字符代表的原本数字
* 因为在编码中间每个字符用base64码表进行了替换,所以这里要先换回来
* 在对换回来的数字进行位运算使其还原成3个字符
*/
void decodeBase64(char* str,int len,char** in){

char ascill[129];
int k = 0;
for(int i=0;i<64;i++){
ascill[base64[i]] = k++;
}
int decodeStrlen = len / 4 * 3 + 1;
char* decodeStr = (char*)malloc(sizeof(char)*decodeStrlen);
k = 0;
for(int i=0;i<len;i++){
decodeStr[k++] = (ascill[str[i]] << 2) | (ascill[str[++i]] >> 4);
if(str[i+1] == '='){
break;
}
decodeStr[k++] = (ascill[str[i]] << 4) | (ascill[str[++i]] >> 2);
if(str[i+1] == '='){
break;
}
decodeStr[k++] = (ascill[str[i]] << 6) | (ascill[str[++i]]);
}
decodeStr[k] = '\0';
*in = decodeStr;
}


int main(){
char mm[]="UAsFvs3tDyTxFPGb7WbyBYSm05VWrJxgjArj9mx490pfH1LO";
char *mm1;
char *mm2;
encodeBase64(mm,strlen(mm),&mm1);
decodeBase64(mm1,strlen(mm1),&mm2);
puts(mm2);
}

XXTEA

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
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
//容易魔改
void btea(uint32_t * v, int n, uint32_t const key[4]) {
//v为数据,n为数据长度(负时为解密),key为密钥
uint32_t y, z, sum; unsigned p, rounds, e;
if (n > 1)
/* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do {
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++) {
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (-- rounds );
} else if (n < -1)
/* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do {
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) {
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (-- rounds );
}
}
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
#include <stdio.h>
#include <stdlib.h>
#define delta 0x9e3779b9

int main()
{
unsigned int v[8] = {0x10BD3B47, 0x6155E0F9, 0x6AF7EBC5, 0x8D23435F, 0x1A091605, 0xD43D40EF, 0xB4B16A67, 0x6B3578A9};
unsigned int key[4] = {0x00001234, 0x00002345, 0x00004567, 0x00006789};
unsigned int sum = 0;
unsigned int y, z, p, rounds, e;
int n = 8;
int i = 0;
rounds = 6 + 52 / n;
y = v[0];
sum = rounds * delta;
do
{
e = sum >> 2 & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
v[p] -= ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((key[(p & 3) ^ e] ^ z) + (y ^ sum)));
y = v[p];
}
z = v[n - 1];
v[0] -= (((key[(p ^ e) & 3] ^ z) + (y ^ sum)) ^ (((y << 2) ^ (z >> 5)) + ((z << 4) ^ (y >> 3))));
y = v[0];
sum = sum - delta;
} while (--rounds);

for (i = 0; i < n; i++)
{
printf("%c%c%c%c", *((char *)&v[i] + 0), *((char *)&v[i] + 1), *((char *)&v[i] + 2), *((char *)&v[i] + 3));
// printf("%c%c%c%c",*((char*)&v[i]+3),*((char*)&v[i]+2),*((char*)&v[i]+1),*((char*)&v[i]+0));
}
return 0;
}

XTea

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
#include <stdio.h>
#include <stdint.h>

void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4])
{
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
for (i = 0; i < num_rounds; i++)
{
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = v0;
v[1] = v1;
}

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4])
{
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
for (i = 0; i < num_rounds; i++)
{
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0;
v[1] = v1;
}

Tea

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
#include <stdio.h>
#include <stdint.h>

void encrypt(uint32_t *v, uint32_t *k)
{
uint32_t v0 = v[0], v1 = v[1], sum = 0, i;
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++)
{
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}
v[0] = v0;
v[1] = v1;
}

void decrypt(uint32_t *v, uint32_t *k)
{
uint32_t v0 = v[0], v1 = v[1], i;
uint32_t delta = 0x9e3779b9;
uint32_t sum = delta * 32;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++)
{
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0;
v[1] = v1;
}

AES

伪代码

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
Cipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)])
begin
byte state[4, Nb]
state = in
AddRoundkey(state, w[0, Nb-1])

for round = 1 step 1 to Nr-1
SubBytes(state)
ShiftRows(state)
MixColumns(state)
AddRoundKey(state, w[round*Nb, (round+1)*Nb - 1])
end

SubBytes(state)
ShiftRows(state)
AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb - 1])

out = state
end

InvCipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr_1)])
begin

byte stae[4, Nb]
state = in

AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb - 1])

for round = Nr-1 step -1 downto 1
InvShiftRows(state)
InvSubBytes(state)
AddRoundKey(state, w[round*Nb, (round+1)*Nb - 1])
InvMixColumns(state)
end

InvShiftRows(state)
InvSubBytes(state)
AddRoundKey(state, w[0, Nb-1])

out = state
end


// 另一种等效的加解密步骤, Intel AES指令集采用的是这种步骤(两者加密密钥扩展是一样的)
// SubBytes和ShiftRows可以交换
// InvMixColumns(AddRoundKey(state, RoundKey)) = AddRoundKey(InvMixColumns(state), InvMixColumns(RoundKey)

Cipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)])
begin
byte state[4, Nb]
state = in
AddRoundkey(state, w[0, Nb-1])

for round = 1 step 1 to Nr-1
ShiftRows(state)
SubBytes(state)
MixColumns(state)
AddRoundKey(state, w[round*Nb, (round+1)*Nb - 1])
end

ShiftRows(state)
SubBytes(state)
AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb - 1])

out = state
end

InvCipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr_1)])
begin

byte stae[4, Nb]
state = in

AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb - 1])

for round = Nr-1 step -1 downto 1
InvSubBytes(state)
InvShiftRows(state)
InvMixColumns(state)
AddRoundKey(state, w[round*Nb, (round+1)*Nb - 1])
end

InvSubBytes(state)
InvShiftRows(state)
AddRoundKey(state, w[0, Nb-1])

out = state
end

// 解密密钥扩展需要增加如下步骤
for i = 0 step 1 to (Nb*(Nr+1)-1)
dw[i] = w[i]
end
// 增加的运算
for round=1 step 1 to Nr-1
InvMixColumns(dw[round*Nb, (round+1)*Nb-1])
end for

代码 1

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
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void AddRoundKey(unsigned char *plaintext, unsigned char * CipherKey)/*轮密钥加*/
{
for (int j = 0; j < 16; j++) plaintext[j] = plaintext[j] ^ CipherKey[j];
}
void SubBytes(unsigned char *plaintext, unsigned char *plaintextencrypt, int count)/*S盒置换*/
{
unsigned int row, column;
unsigned char Sbox[16][16] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/*0*/{ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 },
/*1*/{ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 },
/*2*/{ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 },
/*3*/{ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 },
/*4*/{ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 },
/*5*/{ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf },
/*6*/{ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 },
/*7*/{ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 },
/*8*/{ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 },
/*9*/{ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb },
/*a*/{ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 },
/*b*/{ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 },
/*c*/{ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a },
/*d*/{ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e },
/*e*/{ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf },
/*f*/{ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }
};// 填充Sbox矩阵
for (int i = 0; i < count; i++)
{
row = (plaintext[i] & 0xF0) >> 4;
column = plaintext[i] & 0x0F;
plaintextencrypt[i] = Sbox[row][column];
}
}
void SubBytesRe(unsigned char *plaintext, unsigned char *plaintextencrypt, int count)/*S盒逆置换*/
{
unsigned int row, column;
unsigned char Sbox[16][16] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
{0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb},
{0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb},
{0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e},
{0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25},
{0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92},
{0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84},
{0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06},
{0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b},
{0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73},
{0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e},
{0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b},
{0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4},
{0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f},
{0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef},
{0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61},
{0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}
}; // 填充Sbox矩阵
for (int i = 0; i < count; i++)
{
row = (plaintext[i] & 0xF0) >> 4;
column = plaintext[i] & 0x0F;
plaintextencrypt[i] = Sbox[row][column];
}
}
void ShiftRowsRe(unsigned char *plaintextencrypt)/*行移位的逆*/
{
unsigned char temp = 0;
for (int i = 0; i < 4; i++)//第i行
{
for (int j = 0; j < 4 - i; j++)//第j次左移
{
temp = plaintextencrypt[i];
for (int k = 0; k < 4; k++)
plaintextencrypt[i + 4 * k] = plaintextencrypt[i + 4 * (k + 1)];
plaintextencrypt[i + 12] = temp;
}
}
}
void ShiftRows(unsigned char *plaintextencrypt)/*行移位*/
{
unsigned char temp = 0;
for (int i = 0; i < 4; i++)//第i行
{
for (int j = 0; j < i; j++)//第j次左移
{
temp = plaintextencrypt[i];
for (int k = 0; k < 4; k++)
plaintextencrypt[i + 4 * k] = plaintextencrypt[i + 4 * (k + 1)];
plaintextencrypt[i + 12] = temp;
}
}
}
unsigned char Mult2(unsigned char num)/*列混淆*/
{
unsigned char temp = num << 1;
if ((num >> 7) & 0x01)
temp = temp ^ 27;
return temp;
}
unsigned char Mult3(unsigned char num)
{
return Mult2(num) ^ num;
}
void MixColumns(unsigned char *plaintextencrypt, unsigned char *plaintextcrypt)
{
int i;
for (i = 0; i < 4; i++)
plaintextcrypt[4 * i] = Mult2(plaintextencrypt[4 * i]) ^ Mult3(plaintextencrypt[4 * i + 1]) ^ plaintextencrypt[4 * i + 2] ^ plaintextencrypt[4 * i + 3];
for (i = 0; i < 4; i++)
plaintextcrypt[4 * i + 1] = plaintextencrypt[4 * i] ^ Mult2(plaintextencrypt[4 * i + 1]) ^ Mult3(plaintextencrypt[4 * i + 2]) ^ plaintextencrypt[4 * i + 3];
for (i = 0; i < 4; i++)
plaintextcrypt[4 * i + 2] = plaintextencrypt[4 * i] ^ plaintextencrypt[4 * i + 1] ^ Mult2(plaintextencrypt[4 * i + 2]) ^ Mult3(plaintextencrypt[4 * i + 3]);
for (i = 0; i < 4; i++)
plaintextcrypt[4 * i + 3] = Mult3(plaintextencrypt[4 * i]) ^ plaintextencrypt[4 * i + 1] ^ plaintextencrypt[4 * i + 2] ^ Mult2(plaintextencrypt[4 * i + 3]);
}
/*逆列混淆*/
#define xtime(x) ((x<<1) ^ (((x>>7) & 1) * 0x1b))
#define Multiply(x,y) (((y & 1) * x) ^ ((y>>1 & 1) * xtime(x)) ^ ((y>>2 & 1) * xtime(xtime(x))) ^ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x))))))
void MixColumnsRe(unsigned char *state)
{

unsigned char a, b, c, d;
for (int i = 0; i < 4; i++)
{
a = state[4*i];
b = state[4*i+1];
c = state[4*i+2];
d = state[4*i+3];
state[4 * i] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
state[4 * i + 1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
state[4 * i + 2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
state[4 * i + 3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
}
}
int CharToWord(unsigned char *character, int first)/*字节转字*/
{
return (((int)character[first] & 0x000000ff) << 24) | (((int)character[first + 1] & 0x000000ff) << 16) | (((int)character[first + 2] & 0x000000ff) << 8) | ((int)character[first + 3] & 0x000000ff);
}
void WordToChar(unsigned int word, unsigned char *character)/*字转字节*/
{
for (int i = 0; i < 4; character[i++] = (word >> (8 * (3 - i))) & 0xFF);
}
void ExtendCipherKey(unsigned int *CipherKey_word, int round)/*密钥扩展*/
{
unsigned char CipherKeyChar[4] = { 0 },CipherKeyCharEncrypt[4] = { 0 };
unsigned int Rcon[10] = { 0x01000000,0x02000000,0x04000000,0x08000000,0x10000000,0x20000000,0x40000000,0x80000000,0x1B000000,0x36000000 }; //轮常量
for (int i = 4; i < 8; i++)
{
if (!(i % 4))
{
WordToChar((CipherKey_word[i - 1] >> 24) | (CipherKey_word[i - 1] << 8), CipherKeyChar);
SubBytes(CipherKeyChar, CipherKeyCharEncrypt, 4);
CipherKey_word[i] = CipherKey_word[i - 4] ^ CharToWord(CipherKeyCharEncrypt, 0) ^ Rcon[round];
}
else
CipherKey_word[i] = CipherKey_word[i - 4] ^ CipherKey_word[i - 1];
}
}
void main()
{
printf("**************AES加解密***************\n");
int i = 0, k;
unsigned char PlainText[16] = { 0x32,0x43,0xf6,0xa8,0x88,0x5a,0x30,0x8d,0x31,0x31,0x98,0xa2,0xe0,0x37,0x07,0x34 },
CipherKey[16] = { 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c },
CipherKey1[16] = { 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c },
PlainText1[16] = { 0 },
PlainText2[16] = { 0 };
unsigned int CipherKey_word[44] = { 0 };
for (i = 0; i < 4; CipherKey_word[i++] = CharToWord(CipherKey, 4 * i));
printf("密钥:");
for (k = 0; k < 16; k++) printf("%2X ", CipherKey[k]);
printf("\n明文:");
for (k = 0; k < 16; k++) printf("%02X ", PlainText[k]);
printf("\n**************开始加密****************");
AddRoundKey(PlainText, CipherKey);
for (i = 0; i < 9; i++)
{
printf("\n第%d轮循环:\n", i + 1);
SubBytes(PlainText, PlainText1, 16);/*S盒置换*/
ShiftRows(PlainText1); /*行移位*/
MixColumns(PlainText1, PlainText2); /*列混淆*/
ExtendCipherKey(CipherKey_word + 4 * i, i);/*子密钥生成*/
for (k = 0; k < 4; k++) WordToChar(CipherKey_word[k + 4 * (i + 1)], CipherKey + 4 * k);
printf("此时的子密钥为: ");
for (k = 0; k < 16; k++) printf("%02X ", CipherKey[k]);
AddRoundKey(PlainText2, CipherKey);/*轮密钥加*/
for (k = 0; k < 16; k++) PlainText[k] = PlainText2[k];
printf("\n当前明文加密之后为:");
for (k = 0; k < 16; k++) printf("%02X ", PlainText2[k]);
printf("\n");
}
printf("\n最后一次循环:\n");
SubBytes(PlainText, PlainText1, 16);
ShiftRows(PlainText1);
ExtendCipherKey(CipherKey_word + 4 * i, i);
for (k = 0; k < 4;WordToChar(CipherKey_word[k + 4 * (i + 1)], CipherKey + 4 * k), k++);
printf("此时的子密钥为: ");
for (k = 0; k < 16; k++) printf("%02X ", CipherKey[k]);
AddRoundKey(PlainText1, CipherKey);
printf("\n\n最终AES加密后的密文为:");
for (i = 0; i < 16; i++) printf("%02X ", PlainText1[i]);
printf("\n\n**************开始解密***************");
AddRoundKey(PlainText1, CipherKey);
for (i = 0; i < 9; i++)
{
printf("\n第%d次循环:", i + 1);
SubBytesRe(PlainText1, PlainText, 16);/*S盒置换*/
for (k = 0; k < 4; WordToChar(CipherKey_word[k + 40 - 4 * (i + 1)], CipherKey + 4 * k),k++);/*子密钥生成*/
ShiftRowsRe(PlainText);/*行移位逆*/
AddRoundKey(PlainText, CipherKey);/*轮密钥加*/
MixColumnsRe(PlainText);/*列混淆逆运算*/
for (k = 0; k < 16;PlainText1[k] = PlainText[k],k++);
printf("\n当前密文解密之后为:");
for (k = 0; k < 16; k++)printf("%02X ", PlainText[k]);
printf("\n");
}
printf("\n最后一次循环:");
ShiftRowsRe(PlainText);/*行移位逆*/
SubBytesRe(PlainText, PlainText1, 16);/*S盒置换*/
AddRoundKey(PlainText1, CipherKey1);
printf("\n最终AES解密后的明文为:");
for (i = 0; i < 16; i++) printf("%02X ", PlainText1[i]);
printf("\n");
system("pause");
}

代码 2

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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
//
// Created by Liming Shao on 2018/4/24.
//

#include <stdint.h>
#include <stdio.h>
#include <string.h>

typedef struct{
uint32_t eK[44], dK[44]; // encKey, decKey
int Nr; // 10 rounds
} AesKey;

#define BLOCKSIZE 16

#define LOAD32H(x, y) \
do { (x) = ((uint32_t)((y)[0] & 0xff)<<24) | ((uint32_t)((y)[1] & 0xff)<<16) | \
((uint32_t)((y)[2] & 0xff)<<8) | ((uint32_t)((y)[3] & 0xff));} while(0)

#define STORE32H(x, y) \
do { (y)[0] = (uint8_t)(((x)>>24) & 0xff); (y)[1] = (uint8_t)(((x)>>16) & 0xff); \
(y)[2] = (uint8_t)(((x)>>8) & 0xff); (y)[3] = (uint8_t)((x) & 0xff); } while(0)

/* extract a byte */
#define BYTE(x, n) (((x) >> (8 * (n))) & 0xff)

/* used for keyExpansion */
#define MIX(x) (((S[BYTE(x, 2)] << 24) & 0xff000000) ^ ((S[BYTE(x, 1)] << 16) & 0xff0000) ^ \
((S[BYTE(x, 0)] << 8) & 0xff00) ^ (S[BYTE(x, 3)] & 0xff))

#define ROF32(x, n) (((x) << (n)) | ((x) >> (32-(n))))

#define ROR32(x, n) (((x) >> (n)) | ((x) << (32-(n))))

/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
static const uint32_t rcon[10] = {
0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL,
0x20000000UL, 0x40000000UL, 0x80000000UL, 0x1B000000UL, 0x36000000UL
};

unsigned char S[256] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};

// unsigned char inv_S[256] = {
// 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
// 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
// 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
// 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
// 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
// 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
// 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
// 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
// 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
// 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
// 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
// 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
// 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
// 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
// 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
// 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
// };

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

/* copy in[16] to state[4][4] */
int loadStateArray(uint8_t (*state)[4], const uint8_t *in) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[j][i] = *in++;
}
}
return 0;
}

/* copy state[4][4] to out[16] */
int storeStateArray(uint8_t (*state)[4], uint8_t *out) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
*out++ = state[j][i];
}
}
return 0;
}

int keyExpansion(const uint8_t *key, uint32_t keyLen, AesKey *aesKey) {

if (NULL == key || NULL == aesKey){
printf("keyExpansion param is NULL\n");
return -1;
}

if (keyLen != 16){
printf("keyExpansion keyLen = %d, Not support.\n", keyLen);
return -1;
}

uint32_t *w = aesKey->eK;
uint32_t *v = aesKey->dK;

/* keyLen is 16 Bytes, generate uint32_t W[44]. */

/* W[0-3] */
for (int i = 0; i < 4; ++i) {
LOAD32H(w[i], key + 4*i);
}

/* W[4-43] */
for (int i = 0; i < 10; ++i) {
w[4] = w[0] ^ MIX(w[3]) ^ rcon[i];
w[5] = w[1] ^ w[4];
w[6] = w[2] ^ w[5];
w[7] = w[3] ^ w[6];
w += 4;
}

w = aesKey->eK+44 - 4;
for (int j = 0; j < 11; ++j) {

for (int i = 0; i < 4; ++i) {
v[i] = w[i];
}
w -= 4;
v += 4;
}

return 0;
}

int addRoundKey(uint8_t (*state)[4], const uint32_t *key) {
uint8_t k[4][4];

/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
k[i][j] = (uint8_t) BYTE(key[j], 3 - i); /* copy uint32 key[4] to uint8 k[4][4] */
state[i][j] ^= k[i][j];
}
}

return 0;
}

int subBytes(uint8_t (*state)[4]) {
/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = S[state[i][j]];
}
}

return 0;
}

int invSubBytes(uint8_t (*state)[4]) {
/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = inv_S[state[i][j]];
}
}

return 0;
}

int shiftRows(uint8_t (*state)[4]) {
uint32_t block[4] = {0};

/* i: row */
for (int i = 0; i < 4; ++i) {
LOAD32H(block[i], state[i]);
block[i] = ROF32(block[i], 8*i);
STORE32H(block[i], state[i]);
}

return 0;
}

int invShiftRows(uint8_t (*state)[4]) {
uint32_t block[4] = {0};

/* i: row */
for (int i = 0; i < 4; ++i) {
LOAD32H(block[i], state[i]);
block[i] = ROR32(block[i], 8*i);
STORE32H(block[i], state[i]);
}

return 0;
}

/* Galois Field (256) Multiplication of two Bytes */
uint8_t GMul(uint8_t u, uint8_t v) {
uint8_t p = 0;

for (int i = 0; i < 8; ++i) {
if (u & 0x01) { //
p ^= v;
}

int flag = (v & 0x80);
v <<= 1;
if (flag) {
v ^= 0x1B; /* x^8 + x^4 + x^3 + x + 1 */
}

u >>= 1;
}

return p;
}

int mixColumns(uint8_t (*state)[4]) {
uint8_t tmp[4][4];
uint8_t M[4][4] = {{0x02, 0x03, 0x01, 0x01},
{0x01, 0x02, 0x03, 0x01},
{0x01, 0x01, 0x02, 0x03},
{0x03, 0x01, 0x01, 0x02}};

/* copy state[4][4] to tmp[4][4] */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j){
tmp[i][j] = state[i][j];
}
}

for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j])
^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]);
}
}

return 0;
}

int invMixColumns(uint8_t (*state)[4]) {
uint8_t tmp[4][4];
uint8_t M[4][4] = {{0x0E, 0x0B, 0x0D, 0x09},
{0x09, 0x0E, 0x0B, 0x0D},
{0x0D, 0x09, 0x0E, 0x0B},
{0x0B, 0x0D, 0x09, 0x0E}};

/* copy state[4][4] to tmp[4][4] */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j){
tmp[i][j] = state[i][j];
}
}

for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j])
^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]);
}
}

return 0;
}

int aesEncrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *pt, uint8_t *ct, uint32_t len) {

AesKey aesKey;
uint8_t *pos = ct;
const uint32_t *rk = aesKey.eK;
uint8_t out[BLOCKSIZE] = {0};
uint8_t actualKey[16] = {0};
uint8_t state[4][4] = {0};

if (NULL == key || NULL == pt || NULL == ct){
printf("param err.\n");
return -1;
}

if (keyLen > 16){
printf("keyLen must be 16.\n");
return -1;
}

if (len % BLOCKSIZE){
printf("inLen is invalid.\n");
return -1;
}

memcpy(actualKey, key, keyLen);
keyExpansion(actualKey, 16, &aesKey);

for (int i = 0; i < len; i += BLOCKSIZE) {

loadStateArray(state, pt);
addRoundKey(state, rk);

for (int j = 1; j < 10; ++j) {
rk += 4;
subBytes(state);
shiftRows(state);
mixColumns(state);
addRoundKey(state, rk);
}

subBytes(state);
shiftRows(state);
addRoundKey(state, rk+4);

storeStateArray(state, pos);

pos += BLOCKSIZE;
pt += BLOCKSIZE;
rk = aesKey.eK;
}
return 0;
}

int aesDecrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *ct, uint8_t *pt, uint32_t len) {
AesKey aesKey;
uint8_t *pos = pt;
const uint32_t *rk = aesKey.dK;
uint8_t out[BLOCKSIZE] = {0};
uint8_t actualKey[16] = {0};
uint8_t state[4][4] = {0};

if (NULL == key || NULL == ct || NULL == pt){
printf("param err.\n");
return -1;
}

if (keyLen > 16){
printf("keyLen must be 16.\n");
return -1;
}

if (len % BLOCKSIZE){
printf("inLen is invalid.\n");
return -1;
}

memcpy(actualKey, key, keyLen);
keyExpansion(actualKey, 16, &aesKey);

for (int i = 0; i < len; i += BLOCKSIZE) {
loadStateArray(state, ct);
addRoundKey(state, rk);

for (int j = 1; j < 10; ++j) {
rk += 4;
invShiftRows(state);
invSubBytes(state);
addRoundKey(state, rk);
invMixColumns(state);
}

invSubBytes(state);
invShiftRows(state);
addRoundKey(state, rk+4);

storeStateArray(state, pos);
pos += BLOCKSIZE;
ct += BLOCKSIZE;
rk = aesKey.dK;
}
return 0;
}

void printHex(const uint8_t *ptr, int len, char *tag) {
printf("%s\ndata[%d]: ", tag, len);
for (int i = 0; i < len; ++i) {
printf("%.2X ", *ptr++);
}
printf("\n");
}

void printState(uint8_t (*state)[4], char *tag) {
printf("%s\n", tag);
for (int i = 0; i < 4; ++i) {
printf("%.2X %.2X %.2X %.2X\n", state[i][0], state[i][1], state[i][2], state[i][3]);
}
printf("\n");
}

int main() {

// case 1
const uint8_t key[16] = { 0x05,0x06,0x07,0x08,0x37,0x42,0x4d,0x58,0x63,0x00,0x0a,0x0c,0x0d,0x0e,0x0f,0x10 };
const uint8_t pt[48]={
0x71,0x55,0x7f,0xa8,0xfa,0x0e,0xa3,0x19,0xa0,0x5c,0xf9,0x0e,0x9b,0x0b,0x5e,0xfc,0xb5,0xa8,0x49,0xfd,0x90,0x99,0x74,0xc7,0x77,0x02,0x6a,0xf5,0x9a,0x6a,0xba,0x7f,0xfb,0xe7,0x68,0xda,0x54,0xee,0xe8,0xbb,0x78,0x01,0xe7,0xbb,0xa2,0x95,0x95,0xfa,0x00,0x00
};
uint8_t ct[48] = {0};
uint8_t plain[48] = {0};

// aesEncrypt(key, 16, pt, ct, 16);
// printHex(pt, 16, "plain data:");
// printf("expect cipher:\n39 25 84 1D 02 DC 09 FB DC 11 85 97 19 6A 0B 32\n");

// printHex(ct, 16, "after encryption:");

aesDecrypt(key, 16, pt, plain, 48);
printHex(plain, 48, "after decryption:");

// // case 2
// const uint8_t key2[]="1234567890123456";
// const uint8_t *data = (uint8_t*)"abcdefghijklmnopqrstuvwxyz123456";
// uint8_t ct2[32] = {0};
// uint8_t plain2[32] = {0};
// aesEncrypt(key2, 16, data, ct2, 32);

// printf("\nplain text:\n%s\n", data);
// printf("expect ciphertext:\nfcad715bd73b5cb0488f840f3bad7889\n");
// printHex(ct2, 32, "after encryption:");

// aesDecrypt(key2, 16, ct2, plain2, 32);
// printHex(plain2, 32, "after decryption:");

// printf("output plain text\n");
// for (int i = 0; i < 32; ++i) {
// printf("%c ", plain2[i]);
// }

return 0;
}

逆盒脚本

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
#include "stdio.h"
#include "stdint.h"

unsigned char S[256] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};

uint8_t INV_S[256] = {};

int main() {
for (size_t i = 0; i < 256; i++)
{
// 脱裤子放屁,,, 等于 INV_S[S[i]] = i;
INV_S[(((S[i] & 0xF0) >> 4) << 4) + (S[i] & 0xF)] = i;
}

for (size_t i = 0; i < 256; i++)
{
printf("%x", INV_S[i]);
if (i < 255) printf(", ");
}
printf("\n");

return 0;
}

BlowFish

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
// 轮函数
DWORD Feistel(DWORD x)
{
DWORD h = S[0][x >> 24] + S[1][x >> 16 & 0xff];
return (h ^ S[2][x >> 8 & 0xff]) + S[3][x & 0xff];
}
void encrypt(DWORD& XL, DWORD& XR)
{
for (int i = 0; i < 16; i += 2)
{
XL ^= P[i];
XR ^= Feistel(XL);
XR ^= P[i + 1];
XL ^= Feistel(XR);
}
XL ^= P[16];
XR ^= P[17];
swap(XL, XR);
}

void decrypt(DWORD& XL, DWORD& XR)
{
for (int i = 16; i > 0; i -= 2)
{
XL ^= P[i + 1];
XR ^= Feistel(XL);
XR ^= P[i];
XL ^= Feistel(XR);
}
XL ^= P[1];
XR ^= P[0];
swap(XL, XR);
}

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
from Crypto.Cipher import Blowfish
import codecs

class BlowfishCipher:
def __init__(self):
pass

def encrypt(self, plaintext, key):
key = key.encode("utf-8")
cipher = Blowfish.new(key, Blowfish.MODE_ECB)

# 将明文填充到8字节的倍数
plaintext = plaintext.ljust((len(plaintext) + 7) // 8 * 8)

ciphertext = cipher.encrypt(plaintext.encode('utf-8'))
hex_encode = codecs.encode(ciphertext, 'hex_codec').decode('utf-8')
return hex_encode

def decrypt(self, ciphertext, key):
key = key.encode("utf-8")
cipher = Blowfish.new(key, Blowfish.MODE_ECB)

ciphertext = codecs.decode(ciphertext, 'hex_codec')
decrypted_text = cipher.decrypt(ciphertext).decode('utf-8').rstrip()
return decrypted_text

if __name__ == '__main__':
plaintext = ''
key = 'UzBtZTBuZV9EMGcz'

blowfish_cipher = BlowfishCipher()
encrypted_text='11a51f049550e2508f17e16cf1632b47'
decrypted_text = blowfish_cipher.decrypt(encrypted_text, key)
print(f"加密: {encrypted_text}, 解密: {decrypted_text}")

SM4

加解密同源

代码1

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
#include<stdio.h>
#define u8 unsigned char
#define u32 unsigned long

// S盒
const u8 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
};

// 密钥扩展算法的常数FK
const u32 FK[4] = {
0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc
};

// 密钥扩展算法的固定参数CK
const u32 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
};

u32 functionB(u32 b); // 查S盒的函数B
u32 loopLeft(u32 a, short length); // 循环左移函数
u32 functionL1(u32 a); // 线性变换L
u32 functionL2(u32 a); // 线性变换L'
u32 functionT(u32 a, short mode); // 合成变换T
void extendFirst(u32 MK[], u32 K[]); // 密钥扩展算法第一步
void extendSecond(u32 RK[], u32 K[]); // 密钥扩展算法第二步
void getRK(u32 MK[], u32 K[], u32 RK[]); // 轮密钥获取算法
void iterate32(u32 X[], u32 RK[]); // 迭代算法
void reverse(u32 X[], u32 Y[]); // 反转函数
void encryptSM4(u32 X[], u32 RK[], u32 Y[]); // 加密算法
void decryptSM4(u32 X[], u32 RK[], u32 Y[]); // 解密算法

/*
查S盒的函数B
参数: u32 b
返回值: 查S盒的结果u32 b
*/
u32 functionB(u32 b) {
u8 a[4];
short i;
a[0] = b / 0x1000000;
a[1] = b / 0x10000;
a[2] = b / 0x100;
a[3] = b;
b = Sbox[a[0]] * 0x1000000 + Sbox[a[1]] * 0x10000 + Sbox[a[2]] * 0x100 + Sbox[a[3]];
return b;
}

/*
循环左移算法
参数: u32 a length:循环左移位数
返回值:u32 b
*/
u32 loopLeft(u32 a, short length) {
short i;
for(i = 0; i < length; i++) {
a = a * 2 + a / 0x80000000;
}
return a;
}

/*
密钥线性变换函数L
参数: u32 a
返回值:线性变换后的u32 a
*/
u32 functionL1(u32 a) {
return a ^ loopLeft(a, 2) ^ loopLeft(a, 10) ^ loopLeft(a, 18) ^ loopLeft(a, 24);
}

/*
密钥线性变换函数L'
参数: u32 a
返回值:移位操作后的u32 a
*/
u32 functionL2(u32 a) {
return a ^ loopLeft(a, 13) ^ loopLeft(a, 23);
}

/*
合成变换T
参数: u32 a short mode:1表示明文的T,调用L;2表示密钥的T,调用L'
返回值:合成变换后的u32 a
*/
u32 functionT(u32 a, short mode) {
return mode == 1 ? functionL1(functionB(a)) : functionL2(functionB(a));
}

/*
密钥扩展算法第一步
参数: MK[4]:密钥 K[4]:中间数据,保存结果 (FK[4]:常数)
返回值:无
*/
void extendFirst(u32 MK[], u32 K[]) {
int i;
for(i = 0; i < 4; i++) {
K[i] = MK[i] ^ FK[i];
}
}

/*
密钥扩展算法第二步
参数: RK[32]:轮密钥,保存结果 K[4]:中间数据 (CK[32]:固定参数)
返回值:无
*/
void extendSecond(u32 RK[], u32 K[]) {
short i;
for(i = 0; i <32; i++) {
K[(i+4)%4] = K[i%4] ^ functionT(K[(i+1)%4] ^ K[(i+2)%4] ^ K[(i+3)%4] ^ CK[i], 2);
RK[i] = K[(i+4)%4];
}
}

/*
密钥扩展算法
参数: MK[4]:密钥 K[4]:中间数据 RK[32]:轮密钥,保存结果
返回值:无
*/
void getRK(u32 MK[], u32 K[], u32 RK[]) {
extendFirst(MK, K);
extendSecond(RK, K);
}

/*
迭代32次
参数: u32 X[4]:迭代对象,保存结果 u32 RK[32]:轮密钥
返回值:无
*/
void iterate32(u32 X[], u32 RK[]) {
short i;
for(i = 0; i < 32; i++) {
X[(i+4)%4] = X[i%4] ^ functionT(X[(i+1)%4] ^ X[(i+2)%4] ^ X[(i+3)%4] ^ RK[i], 1);
}
}

/*
反转函数
参数; u32 X[4]:反转对象 u32 Y[4]:反转结果
返回值:无
*/
void reverse(u32 X[], u32 Y[]) {
short i;
for(i = 0; i < 4; i++){
Y[i] = X[4 - 1 - i];
}
}

/*
加密算法
参数: u32 X[4]:明文 u32 RK[32]:轮密钥 u32 Y[4]:密文,保存结果
返回值:无
*/
void encryptSM4(u32 X[], u32 RK[], u32 Y[]) {
iterate32(X, RK);
reverse(X, Y);
}

/*
解密算法
参数: u32 X[4]:密文 u32 RK[32]:轮密钥 u32 Y[4]:明文,保存结果
返回值:无
*/
void decryptSM4(u32 X[], u32 RK[], u32 Y[]) {
short i;
u32 reverseRK[32];
for(i = 0; i < 32; i++) {
reverseRK[i] = RK[32-1-i];
}
iterate32(X, reverseRK);
reverse(X, Y);
}

/*
测试数据:
明文: 01234567 89abcdef fedcba98 76543210
密钥: 01234567 89abcdef fedcba98 76543210
密文: 681edf34 d206965e 86b3e94f 536e4246
*/
int main(void) {
u32 X[4]; // 明文
u32 MK[4]; // 密钥
u32 RK[32]; // 轮密钥
u32 K[4]; // 中间数据
u32 Y[4]; // 密文
short i; // 临时变量
printf("明文:");
scanf("%8x%8x%8x%8x", &X[0], &X[1], &X[2], &X[3]);
printf("密钥:");
scanf("%8x%8x%8x%8x", &MK[0], &MK[1], &MK[2], &MK[3]);
printf("**************生成轮密钥*****************\n");
getRK(MK, K, RK);
for(i = 0; i < 32; i++) {
printf("[%2d]:%08x ", i, RK[i]);
if(i%4 == 3) printf("\n");
}
printf("************** 生成密文 *****************\n");
encryptSM4(X, RK, Y);
printf("%08x %08x %08x %08x\n", Y[0], Y[1], Y[2], Y[3]);
printf("************** 生成明文 *****************\n");
decryptSM4(Y, RK, X);
printf("%08x %08x %08x %08x\n", X[0], X[1], X[2], X[3]);
return 0;
}

代码2

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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
/*
* SM4 Encryption alogrithm (SMS4 algorithm)
* GM/T 0002-2012 Chinese National Standard ref:http://www.oscca.gov.cn/
* thanks to Xyssl
* thnaks and refers to http://hi.baidu.com/numax/blog/item/80addfefddfb93e4cf1b3e61.html
* author:goldboar
* email:goldboar@163.com
* 2012-4-20
*/
#define SM4_ENCRYPT 1
#define SM4_DECRYPT 0

typedef unsigned char uint8;
typedef unsigned int uint32;

/**
* \brief SM4 context structure
*/
typedef struct
{
int mode; /*!< encrypt/decrypt */
uint32 sk[32]; /*!< SM4 subkeys */
} sm4_context;

/**
* \brief SM4 key schedule (128-bit, encryption)
*
* \param ctx SM4 context to be initialized
* \param key 16-byte secret key
*/
void sm4_setkey_enc(sm4_context *ctx, uint8 key[16]);

/**
* \brief SM4 key schedule (128-bit, decryption)
*
* \param ctx SM4 context to be initialized
* \param key 16-byte secret key
*/
void sm4_setkey_dec(sm4_context *ctx, uint8 key[16]);

/**
* \brief SM4-ECB block encryption/decryption
* \param ctx SM4 context
* \param mode SM4_ENCRYPT or SM4_DECRYPT
* \param length length of the input data
* \param input input block
* \param output output block
*/
void sm4_crypt_ecb(sm4_context *ctx,
int mode,
int length,
uint8 *input,
uint8 *output);

/**
* \brief SM4-CBC buffer encryption/decryption
* \param ctx SM4 context
* \param mode SM4_ENCRYPT or SM4_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*/
void sm4_crypt_cbc(sm4_context *ctx,
int mode,
int length,
uint8 iv[16],
uint8 *input,
uint8 *output);

#include <string.h>
#include <stdio.h>
#include <time.h>
#include <ctype.h>

/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n, b, i) \
{ \
(n) = ((uint32)(b)[(i)] << 24) | ((uint32)(b)[(i) + 1] << 16) | ((uint32)(b)[(i) + 2] << 8) | ((uint32)(b)[(i) + 3]); \
}
#endif

#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n, b, i) \
{ \
(b)[(i)] = (uint8)((n) >> 24); \
(b)[(i) + 1] = (uint8)((n) >> 16); \
(b)[(i) + 2] = (uint8)((n) >> 8); \
(b)[(i) + 3] = (uint8)((n)); \
}
#endif

/*
*rotate shift left marco definition
*
*/
#define SHL(x, n) (((x) & 0xFFFFFFFF) << n)
#define ROTL(x, n) (SHL((x), n) | ((x) >> (32 - n)))

#define SWAP(a, b) \
{ \
uint32 t = a; \
a = b; \
b = t; \
t = 0; \
}

/*
* Expanded SM4 S-boxes
/* Sbox table: 8bits input convert to 8 bits output*/

static const uint8 SboxTable[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}
};

/* System parameter */
static const uint32 FK[4] = {0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc};

/* fixed parameter */
static const uint32 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
};

/*
* private function:
* look up in SboxTable and get the related value.
* args: [in] inch: 0x00~0xFF (8 bits unsigned value).
*/
static uint8 sm4Sbox(uint8 inch)
{
uint8 *pTable = (uint8 *)SboxTable;
uint8 retVal = (uint8)(pTable[inch]);
return retVal;
}

void printHex_withSpace(char *name, void *ptr, int len);
void hexdump(char *name, const void *data, size_t size);

/*
* private F(Lt) function:
* "T algorithm" == "L algorithm" + "t algorithm".
* args: [in] a: a is a 32 bits unsigned value;
* return: c: c is calculated with line algorithm "L" and nonline algorithm "t"
*/
static uint32 sm4Lt(uint32 ka)
{
uint32 bb = 0;
uint32 c = 0;

uint8 a[4];
uint8 b[4];

PUT_UINT32_BE(ka, a, 0)

b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);

GET_UINT32_BE(bb, b, 0)

c = bb ^ (ROTL(bb, 2)) ^ (ROTL(bb, 10)) ^ (ROTL(bb, 18)) ^ (ROTL(bb, 24));
return c;
}

/*
* private F function:
* Calculating and getting encryption/decryption contents.
* args: [in] x0: original contents;
* args: [in] x1: original contents;
* args: [in] x2: original contents;
* args: [in] x3: original contents;
* args: [in] rk: encryption/decryption key;
* return the contents of encryption/decryption contents.
*/
static uint32 sm4F(uint32 x0, uint32 x1, uint32 x2, uint32 x3, uint32 rk)
{
return (x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk));
}

/* private function:
* Calculating round encryption key.
* args: [in] a: a is a 32 bits unsigned value;
* return: sk[i]: i{0,1,2,3,...31}.
*/
static uint32 sm4CalciRK(uint32 ka)
{
uint32 bb = 0;
uint32 rk = 0;

uint8 a[4];
uint8 b[4];

PUT_UINT32_BE(ka, a, 0)

b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);

GET_UINT32_BE(bb, b, 0)

rk = bb ^ (ROTL(bb, 13)) ^ (ROTL(bb, 23));

return rk;
}

static void sm4_setkey(uint32 SK[32], uint8 key[16])
{
uint32 MK[4];
uint32 k[36];
uint32 i = 0;

GET_UINT32_BE(MK[0], key, 0);
GET_UINT32_BE(MK[1], key, 4);
GET_UINT32_BE(MK[2], key, 8);
GET_UINT32_BE(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 (; i < 32; i++)
{
k[i + 4] = k[i] ^ (sm4CalciRK(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i]));
SK[i] = k[i + 4];
}
}

/*
* SM4 standard one round processing
*
*/
static void sm4_one_round(uint32 sk[32],
uint8 input[16],
uint8 output[16])
{
uint32 i = 0;
uint32 ulbuf[36];

memset(ulbuf, 0, sizeof(ulbuf));
GET_UINT32_BE(ulbuf[0], input, 0)
GET_UINT32_BE(ulbuf[1], input, 4)
GET_UINT32_BE(ulbuf[2], input, 8)
GET_UINT32_BE(ulbuf[3], input, 12)

while (i < 32)
{
ulbuf[i + 4] = sm4F(ulbuf[i], ulbuf[i + 1], ulbuf[i + 2], ulbuf[i + 3], sk[i]);
i++;
}

PUT_UINT32_BE(ulbuf[35], output, 0);
PUT_UINT32_BE(ulbuf[34], output, 4);
PUT_UINT32_BE(ulbuf[33], output, 8);
PUT_UINT32_BE(ulbuf[32], output, 12);
}

/*
* SM4 key schedule (128-bit, encryption)
*/
void sm4_setkey_enc(sm4_context *ctx, uint8 key[16])
{
ctx->mode = SM4_ENCRYPT;
sm4_setkey(ctx->sk, key);
}

/*
* SM4 key schedule (128-bit, decryption)
*/
void sm4_setkey_dec(sm4_context *ctx, uint8 key[16])
{
int i;
ctx->mode = SM4_ENCRYPT;
sm4_setkey(ctx->sk, key);
for (i = 0; i < 16; i++)
{
SWAP(ctx->sk[i], ctx->sk[31 - i]);
}
}

/*
* SM4-ECB block encryption/decryption
*/

void sm4_crypt_ecb(sm4_context *ctx,
int mode,
int length,
uint8 *input,
uint8 *output)
{
while (length > 0)
{
sm4_one_round(ctx->sk, input, output);
input += 16;
output += 16;
length -= 16;
}
}

/*
* SM4-CBC buffer encryption/decryption
*/
void sm4_crypt_cbc(sm4_context *ctx,
int mode,
int length,
uint8 iv[16],
uint8 *input,
uint8 *output)
{
int i;
uint8 temp[16];

if (mode == SM4_ENCRYPT)
{
while (length > 0)
{
for (i = 0; i < 16; i++)
output[i] = (uint8)(input[i] ^ iv[i]);

sm4_one_round(ctx->sk, output, output);
memcpy(iv, output, 16);

input += 16;
output += 16;
length -= 16;
}
}
else /* SM4_DECRYPT */
{
while (length > 0)
{
memcpy(temp, input, 16);
sm4_one_round(ctx->sk, input, output);

for (i = 0; i < 16; i++)
output[i] = (uint8)(output[i] ^ iv[i]);

memcpy(iv, temp, 16);

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

void printHex(char *name, void *ptr, int len)
{
printf("%s", name);
for (size_t i = 0; i < len; i++)
printf("%02x", ((uint8 *)ptr)[i]);
printf("\n");
}

void printHex_withSpace(char *name, void *ptr, int len)
{
printf("%s\n", name);
for (size_t i = 0; i < len * 4; i++)
printf("%02x ", ((uint8 *)ptr)[i]);
printf("\n");
}

void hexdump(char *name, const void *data, size_t size) {
const unsigned char *byte_data = (const unsigned char *)data;
size_t i, j;

printf("%s\n", name);

for (i = 0; i < size; i += 16) {
// 打印偏移地址
printf("%08zx ", i);

// 打印十六进制数据
for (j = 0; j < 16; ++j) {
if (i + j < size) {
printf("%02x ", byte_data[i + j]);
} else {
printf(" "); // 不足部分用空格填充
}

// 在每8字节后添加一个额外的空格
if (j == 7) {
printf(" ");
}
}

printf(" |");

// 打印ASCII字符
for (j = 0; j < 16; ++j) {
if (i + j < size) {
unsigned char ch = byte_data[i + j];
printf("%c", isprint(ch) ? ch : '.');
} else {
printf(" ");
}
}

printf("|\n");
}
}

int main()
{
uint8 key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
uint8 input[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
uint8 output[16];

sm4_context ctx;
uint32 i;

printHex("Key: ", key, 16);

// encrypt standard testing vector
sm4_setkey_enc(&ctx, key);
hexdump("RK_enc: ", ctx.sk, 32 * 4);

sm4_crypt_ecb(&ctx, 1, 16, input, output);
printHex("Crypted: ", output, 16);

// decrypt testing
sm4_setkey_dec(&ctx, key);
hexdump("RK_dec: ", ctx.sk, 32 * 4);

sm4_crypt_ecb(&ctx, 0, 16, output, output);
printHex("Original: ", output, 16);

return 0;
}

一份利用 SBOX_TX 加速运算的 SM4 代码

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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
#include "stdlib.h"
#include "ctype.h"
#include "stdio.h"

typedef unsigned char uint8_t;
typedef unsigned int uint32_t;

#define SM4_ENCRYPT 1
#define SM4_DECRYPT 0

#define SM4_BLOCK_SIZE 16
#define SM4_KEY_SCHEDULE 32

typedef struct SM4_KEY_st
{
uint32_t rk[SM4_KEY_SCHEDULE];
} SM4_KEY;

static const uint8_t SM4_S[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};

/*
* SM4_SBOX_T[j] == L(SM4_SBOX[j]).
*/
static const uint32_t SM4_SBOX_T0[256] = {
0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787,
0xC93DF4F4, 0x6BB5DEDE, 0x4E165858, 0x6EB4DADA, 0x44145050, 0xCAC10B0B,
0x8828A0A0, 0x17F8EFEF, 0x9C2CB0B0, 0x11051414, 0x872BACAC, 0xFB669D9D,
0xF2986A6A, 0xAE77D9D9, 0x822AA8A8, 0x46BCFAFA, 0x14041010, 0xCFC00F0F,
0x02A8AAAA, 0x54451111, 0x5F134C4C, 0xBE269898, 0x6D482525, 0x9E841A1A,
0x1E061818, 0xFD9B6666, 0xEC9E7272, 0x4A430909, 0x10514141, 0x24F7D3D3,
0xD5934646, 0x53ECBFBF, 0xF89A6262, 0x927BE9E9, 0xFF33CCCC, 0x04555151,
0x270B2C2C, 0x4F420D0D, 0x59EEB7B7, 0xF3CC3F3F, 0x1CAEB2B2, 0xEA638989,
0x74E79393, 0x7FB1CECE, 0x6C1C7070, 0x0DABA6A6, 0xEDCA2727, 0x28082020,
0x48EBA3A3, 0xC1975656, 0x80820202, 0xA3DC7F7F, 0xC4965252, 0x12F9EBEB,
0xA174D5D5, 0xB38D3E3E, 0xC33FFCFC, 0x3EA49A9A, 0x5B461D1D, 0x1B071C1C,
0x3BA59E9E, 0x0CFFF3F3, 0x3FF0CFCF, 0xBF72CDCD, 0x4B175C5C, 0x52B8EAEA,
0x8F810E0E, 0x3D586565, 0xCC3CF0F0, 0x7D196464, 0x7EE59B9B, 0x91871616,
0x734E3D3D, 0x08AAA2A2, 0xC869A1A1, 0xC76AADAD, 0x85830606, 0x7AB0CACA,
0xB570C5C5, 0xF4659191, 0xB2D96B6B, 0xA7892E2E, 0x18FBE3E3, 0x47E8AFAF,
0x330F3C3C, 0x674A2D2D, 0xB071C1C1, 0x0E575959, 0xE99F7676, 0xE135D4D4,
0x661E7878, 0xB4249090, 0x360E3838, 0x265F7979, 0xEF628D8D, 0x38596161,
0x95D24747, 0x2AA08A8A, 0xB1259494, 0xAA228888, 0x8C7DF1F1, 0xD73BECEC,
0x05010404, 0xA5218484, 0x9879E1E1, 0x9B851E1E, 0x84D75353, 0x00000000,
0x5E471919, 0x0B565D5D, 0xE39D7E7E, 0x9FD04F4F, 0xBB279C9C, 0x1A534949,
0x7C4D3131, 0xEE36D8D8, 0x0A020808, 0x7BE49F9F, 0x20A28282, 0xD4C71313,
0xE8CB2323, 0xE69C7A7A, 0x42E9ABAB, 0x43BDFEFE, 0xA2882A2A, 0x9AD14B4B,
0x40410101, 0xDBC41F1F, 0xD838E0E0, 0x61B7D6D6, 0x2FA18E8E, 0x2BF4DFDF,
0x3AF1CBCB, 0xF6CD3B3B, 0x1DFAE7E7, 0xE5608585, 0x41155454, 0x25A38686,
0x60E38383, 0x16ACBABA, 0x295C7575, 0x34A69292, 0xF7996E6E, 0xE434D0D0,
0x721A6868, 0x01545555, 0x19AFB6B6, 0xDF914E4E, 0xFA32C8C8, 0xF030C0C0,
0x21F6D7D7, 0xBC8E3232, 0x75B3C6C6, 0x6FE08F8F, 0x691D7474, 0x2EF5DBDB,
0x6AE18B8B, 0x962EB8B8, 0x8A800A0A, 0xFE679999, 0xE2C92B2B, 0xE0618181,
0xC0C30303, 0x8D29A4A4, 0xAF238C8C, 0x07A9AEAE, 0x390D3434, 0x1F524D4D,
0x764F3939, 0xD36EBDBD, 0x81D65757, 0xB7D86F6F, 0xEB37DCDC, 0x51441515,
0xA6DD7B7B, 0x09FEF7F7, 0xB68C3A3A, 0x932FBCBC, 0x0F030C0C, 0x03FCFFFF,
0xC26BA9A9, 0xBA73C9C9, 0xD96CB5B5, 0xDC6DB1B1, 0x375A6D6D, 0x15504545,
0xB98F3636, 0x771B6C6C, 0x13ADBEBE, 0xDA904A4A, 0x57B9EEEE, 0xA9DE7777,
0x4CBEF2F2, 0x837EFDFD, 0x55114444, 0xBDDA6767, 0x2C5D7171, 0x45400505,
0x631F7C7C, 0x50104040, 0x325B6969, 0xB8DB6363, 0x220A2828, 0xC5C20707,
0xF531C4C4, 0xA88A2222, 0x31A79696, 0xF9CE3737, 0x977AEDED, 0x49BFF6F6,
0x992DB4B4, 0xA475D1D1, 0x90D34343, 0x5A124848, 0x58BAE2E2, 0x71E69797,
0x64B6D2D2, 0x70B2C2C2, 0xAD8B2626, 0xCD68A5A5, 0xCB955E5E, 0x624B2929,
0x3C0C3030, 0xCE945A5A, 0xAB76DDDD, 0x867FF9F9, 0xF1649595, 0x5DBBE6E6,
0x35F2C7C7, 0x2D092424, 0xD1C61717, 0xD66FB9B9, 0xDEC51B1B, 0x94861212,
0x78186060, 0x30F3C3C3, 0x897CF5F5, 0x5CEFB3B3, 0xD23AE8E8, 0xACDF7373,
0x794C3535, 0xA0208080, 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8,
0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121};

static uint32_t SM4_SBOX_T1[256] = {
0x5B8ED55B, 0x42D09242, 0xA74DEAA7, 0xFB06FDFB, 0x33FCCF33, 0x8765E287,
0xF4C93DF4, 0xDE6BB5DE, 0x584E1658, 0xDA6EB4DA, 0x50441450, 0x0BCAC10B,
0xA08828A0, 0xEF17F8EF, 0xB09C2CB0, 0x14110514, 0xAC872BAC, 0x9DFB669D,
0x6AF2986A, 0xD9AE77D9, 0xA8822AA8, 0xFA46BCFA, 0x10140410, 0x0FCFC00F,
0xAA02A8AA, 0x11544511, 0x4C5F134C, 0x98BE2698, 0x256D4825, 0x1A9E841A,
0x181E0618, 0x66FD9B66, 0x72EC9E72, 0x094A4309, 0x41105141, 0xD324F7D3,
0x46D59346, 0xBF53ECBF, 0x62F89A62, 0xE9927BE9, 0xCCFF33CC, 0x51045551,
0x2C270B2C, 0x0D4F420D, 0xB759EEB7, 0x3FF3CC3F, 0xB21CAEB2, 0x89EA6389,
0x9374E793, 0xCE7FB1CE, 0x706C1C70, 0xA60DABA6, 0x27EDCA27, 0x20280820,
0xA348EBA3, 0x56C19756, 0x02808202, 0x7FA3DC7F, 0x52C49652, 0xEB12F9EB,
0xD5A174D5, 0x3EB38D3E, 0xFCC33FFC, 0x9A3EA49A, 0x1D5B461D, 0x1C1B071C,
0x9E3BA59E, 0xF30CFFF3, 0xCF3FF0CF, 0xCDBF72CD, 0x5C4B175C, 0xEA52B8EA,
0x0E8F810E, 0x653D5865, 0xF0CC3CF0, 0x647D1964, 0x9B7EE59B, 0x16918716,
0x3D734E3D, 0xA208AAA2, 0xA1C869A1, 0xADC76AAD, 0x06858306, 0xCA7AB0CA,
0xC5B570C5, 0x91F46591, 0x6BB2D96B, 0x2EA7892E, 0xE318FBE3, 0xAF47E8AF,
0x3C330F3C, 0x2D674A2D, 0xC1B071C1, 0x590E5759, 0x76E99F76, 0xD4E135D4,
0x78661E78, 0x90B42490, 0x38360E38, 0x79265F79, 0x8DEF628D, 0x61385961,
0x4795D247, 0x8A2AA08A, 0x94B12594, 0x88AA2288, 0xF18C7DF1, 0xECD73BEC,
0x04050104, 0x84A52184, 0xE19879E1, 0x1E9B851E, 0x5384D753, 0x00000000,
0x195E4719, 0x5D0B565D, 0x7EE39D7E, 0x4F9FD04F, 0x9CBB279C, 0x491A5349,
0x317C4D31, 0xD8EE36D8, 0x080A0208, 0x9F7BE49F, 0x8220A282, 0x13D4C713,
0x23E8CB23, 0x7AE69C7A, 0xAB42E9AB, 0xFE43BDFE, 0x2AA2882A, 0x4B9AD14B,
0x01404101, 0x1FDBC41F, 0xE0D838E0, 0xD661B7D6, 0x8E2FA18E, 0xDF2BF4DF,
0xCB3AF1CB, 0x3BF6CD3B, 0xE71DFAE7, 0x85E56085, 0x54411554, 0x8625A386,
0x8360E383, 0xBA16ACBA, 0x75295C75, 0x9234A692, 0x6EF7996E, 0xD0E434D0,
0x68721A68, 0x55015455, 0xB619AFB6, 0x4EDF914E, 0xC8FA32C8, 0xC0F030C0,
0xD721F6D7, 0x32BC8E32, 0xC675B3C6, 0x8F6FE08F, 0x74691D74, 0xDB2EF5DB,
0x8B6AE18B, 0xB8962EB8, 0x0A8A800A, 0x99FE6799, 0x2BE2C92B, 0x81E06181,
0x03C0C303, 0xA48D29A4, 0x8CAF238C, 0xAE07A9AE, 0x34390D34, 0x4D1F524D,
0x39764F39, 0xBDD36EBD, 0x5781D657, 0x6FB7D86F, 0xDCEB37DC, 0x15514415,
0x7BA6DD7B, 0xF709FEF7, 0x3AB68C3A, 0xBC932FBC, 0x0C0F030C, 0xFF03FCFF,
0xA9C26BA9, 0xC9BA73C9, 0xB5D96CB5, 0xB1DC6DB1, 0x6D375A6D, 0x45155045,
0x36B98F36, 0x6C771B6C, 0xBE13ADBE, 0x4ADA904A, 0xEE57B9EE, 0x77A9DE77,
0xF24CBEF2, 0xFD837EFD, 0x44551144, 0x67BDDA67, 0x712C5D71, 0x05454005,
0x7C631F7C, 0x40501040, 0x69325B69, 0x63B8DB63, 0x28220A28, 0x07C5C207,
0xC4F531C4, 0x22A88A22, 0x9631A796, 0x37F9CE37, 0xED977AED, 0xF649BFF6,
0xB4992DB4, 0xD1A475D1, 0x4390D343, 0x485A1248, 0xE258BAE2, 0x9771E697,
0xD264B6D2, 0xC270B2C2, 0x26AD8B26, 0xA5CD68A5, 0x5ECB955E, 0x29624B29,
0x303C0C30, 0x5ACE945A, 0xDDAB76DD, 0xF9867FF9, 0x95F16495, 0xE65DBBE6,
0xC735F2C7, 0x242D0924, 0x17D1C617, 0xB9D66FB9, 0x1BDEC51B, 0x12948612,
0x60781860, 0xC330F3C3, 0xF5897CF5, 0xB35CEFB3, 0xE8D23AE8, 0x73ACDF73,
0x35794C35, 0x80A02080, 0xE59D78E5, 0xBB56EDBB, 0x7D235E7D, 0xF8C63EF8,
0x5F8BD45F, 0x2FE7C82F, 0xE4DD39E4, 0x21684921};

static uint32_t SM4_SBOX_T2[256] = {
0x5B5B8ED5, 0x4242D092, 0xA7A74DEA, 0xFBFB06FD, 0x3333FCCF, 0x878765E2,
0xF4F4C93D, 0xDEDE6BB5, 0x58584E16, 0xDADA6EB4, 0x50504414, 0x0B0BCAC1,
0xA0A08828, 0xEFEF17F8, 0xB0B09C2C, 0x14141105, 0xACAC872B, 0x9D9DFB66,
0x6A6AF298, 0xD9D9AE77, 0xA8A8822A, 0xFAFA46BC, 0x10101404, 0x0F0FCFC0,
0xAAAA02A8, 0x11115445, 0x4C4C5F13, 0x9898BE26, 0x25256D48, 0x1A1A9E84,
0x18181E06, 0x6666FD9B, 0x7272EC9E, 0x09094A43, 0x41411051, 0xD3D324F7,
0x4646D593, 0xBFBF53EC, 0x6262F89A, 0xE9E9927B, 0xCCCCFF33, 0x51510455,
0x2C2C270B, 0x0D0D4F42, 0xB7B759EE, 0x3F3FF3CC, 0xB2B21CAE, 0x8989EA63,
0x939374E7, 0xCECE7FB1, 0x70706C1C, 0xA6A60DAB, 0x2727EDCA, 0x20202808,
0xA3A348EB, 0x5656C197, 0x02028082, 0x7F7FA3DC, 0x5252C496, 0xEBEB12F9,
0xD5D5A174, 0x3E3EB38D, 0xFCFCC33F, 0x9A9A3EA4, 0x1D1D5B46, 0x1C1C1B07,
0x9E9E3BA5, 0xF3F30CFF, 0xCFCF3FF0, 0xCDCDBF72, 0x5C5C4B17, 0xEAEA52B8,
0x0E0E8F81, 0x65653D58, 0xF0F0CC3C, 0x64647D19, 0x9B9B7EE5, 0x16169187,
0x3D3D734E, 0xA2A208AA, 0xA1A1C869, 0xADADC76A, 0x06068583, 0xCACA7AB0,
0xC5C5B570, 0x9191F465, 0x6B6BB2D9, 0x2E2EA789, 0xE3E318FB, 0xAFAF47E8,
0x3C3C330F, 0x2D2D674A, 0xC1C1B071, 0x59590E57, 0x7676E99F, 0xD4D4E135,
0x7878661E, 0x9090B424, 0x3838360E, 0x7979265F, 0x8D8DEF62, 0x61613859,
0x474795D2, 0x8A8A2AA0, 0x9494B125, 0x8888AA22, 0xF1F18C7D, 0xECECD73B,
0x04040501, 0x8484A521, 0xE1E19879, 0x1E1E9B85, 0x535384D7, 0x00000000,
0x19195E47, 0x5D5D0B56, 0x7E7EE39D, 0x4F4F9FD0, 0x9C9CBB27, 0x49491A53,
0x31317C4D, 0xD8D8EE36, 0x08080A02, 0x9F9F7BE4, 0x828220A2, 0x1313D4C7,
0x2323E8CB, 0x7A7AE69C, 0xABAB42E9, 0xFEFE43BD, 0x2A2AA288, 0x4B4B9AD1,
0x01014041, 0x1F1FDBC4, 0xE0E0D838, 0xD6D661B7, 0x8E8E2FA1, 0xDFDF2BF4,
0xCBCB3AF1, 0x3B3BF6CD, 0xE7E71DFA, 0x8585E560, 0x54544115, 0x868625A3,
0x838360E3, 0xBABA16AC, 0x7575295C, 0x929234A6, 0x6E6EF799, 0xD0D0E434,
0x6868721A, 0x55550154, 0xB6B619AF, 0x4E4EDF91, 0xC8C8FA32, 0xC0C0F030,
0xD7D721F6, 0x3232BC8E, 0xC6C675B3, 0x8F8F6FE0, 0x7474691D, 0xDBDB2EF5,
0x8B8B6AE1, 0xB8B8962E, 0x0A0A8A80, 0x9999FE67, 0x2B2BE2C9, 0x8181E061,
0x0303C0C3, 0xA4A48D29, 0x8C8CAF23, 0xAEAE07A9, 0x3434390D, 0x4D4D1F52,
0x3939764F, 0xBDBDD36E, 0x575781D6, 0x6F6FB7D8, 0xDCDCEB37, 0x15155144,
0x7B7BA6DD, 0xF7F709FE, 0x3A3AB68C, 0xBCBC932F, 0x0C0C0F03, 0xFFFF03FC,
0xA9A9C26B, 0xC9C9BA73, 0xB5B5D96C, 0xB1B1DC6D, 0x6D6D375A, 0x45451550,
0x3636B98F, 0x6C6C771B, 0xBEBE13AD, 0x4A4ADA90, 0xEEEE57B9, 0x7777A9DE,
0xF2F24CBE, 0xFDFD837E, 0x44445511, 0x6767BDDA, 0x71712C5D, 0x05054540,
0x7C7C631F, 0x40405010, 0x6969325B, 0x6363B8DB, 0x2828220A, 0x0707C5C2,
0xC4C4F531, 0x2222A88A, 0x969631A7, 0x3737F9CE, 0xEDED977A, 0xF6F649BF,
0xB4B4992D, 0xD1D1A475, 0x434390D3, 0x48485A12, 0xE2E258BA, 0x979771E6,
0xD2D264B6, 0xC2C270B2, 0x2626AD8B, 0xA5A5CD68, 0x5E5ECB95, 0x2929624B,
0x30303C0C, 0x5A5ACE94, 0xDDDDAB76, 0xF9F9867F, 0x9595F164, 0xE6E65DBB,
0xC7C735F2, 0x24242D09, 0x1717D1C6, 0xB9B9D66F, 0x1B1BDEC5, 0x12129486,
0x60607818, 0xC3C330F3, 0xF5F5897C, 0xB3B35CEF, 0xE8E8D23A, 0x7373ACDF,
0x3535794C, 0x8080A020, 0xE5E59D78, 0xBBBB56ED, 0x7D7D235E, 0xF8F8C63E,
0x5F5F8BD4, 0x2F2FE7C8, 0xE4E4DD39, 0x21216849};

static uint32_t SM4_SBOX_T3[256] = {
0xD55B5B8E, 0x924242D0, 0xEAA7A74D, 0xFDFBFB06, 0xCF3333FC, 0xE2878765,
0x3DF4F4C9, 0xB5DEDE6B, 0x1658584E, 0xB4DADA6E, 0x14505044, 0xC10B0BCA,
0x28A0A088, 0xF8EFEF17, 0x2CB0B09C, 0x05141411, 0x2BACAC87, 0x669D9DFB,
0x986A6AF2, 0x77D9D9AE, 0x2AA8A882, 0xBCFAFA46, 0x04101014, 0xC00F0FCF,
0xA8AAAA02, 0x45111154, 0x134C4C5F, 0x269898BE, 0x4825256D, 0x841A1A9E,
0x0618181E, 0x9B6666FD, 0x9E7272EC, 0x4309094A, 0x51414110, 0xF7D3D324,
0x934646D5, 0xECBFBF53, 0x9A6262F8, 0x7BE9E992, 0x33CCCCFF, 0x55515104,
0x0B2C2C27, 0x420D0D4F, 0xEEB7B759, 0xCC3F3FF3, 0xAEB2B21C, 0x638989EA,
0xE7939374, 0xB1CECE7F, 0x1C70706C, 0xABA6A60D, 0xCA2727ED, 0x08202028,
0xEBA3A348, 0x975656C1, 0x82020280, 0xDC7F7FA3, 0x965252C4, 0xF9EBEB12,
0x74D5D5A1, 0x8D3E3EB3, 0x3FFCFCC3, 0xA49A9A3E, 0x461D1D5B, 0x071C1C1B,
0xA59E9E3B, 0xFFF3F30C, 0xF0CFCF3F, 0x72CDCDBF, 0x175C5C4B, 0xB8EAEA52,
0x810E0E8F, 0x5865653D, 0x3CF0F0CC, 0x1964647D, 0xE59B9B7E, 0x87161691,
0x4E3D3D73, 0xAAA2A208, 0x69A1A1C8, 0x6AADADC7, 0x83060685, 0xB0CACA7A,
0x70C5C5B5, 0x659191F4, 0xD96B6BB2, 0x892E2EA7, 0xFBE3E318, 0xE8AFAF47,
0x0F3C3C33, 0x4A2D2D67, 0x71C1C1B0, 0x5759590E, 0x9F7676E9, 0x35D4D4E1,
0x1E787866, 0x249090B4, 0x0E383836, 0x5F797926, 0x628D8DEF, 0x59616138,
0xD2474795, 0xA08A8A2A, 0x259494B1, 0x228888AA, 0x7DF1F18C, 0x3BECECD7,
0x01040405, 0x218484A5, 0x79E1E198, 0x851E1E9B, 0xD7535384, 0x00000000,
0x4719195E, 0x565D5D0B, 0x9D7E7EE3, 0xD04F4F9F, 0x279C9CBB, 0x5349491A,
0x4D31317C, 0x36D8D8EE, 0x0208080A, 0xE49F9F7B, 0xA2828220, 0xC71313D4,
0xCB2323E8, 0x9C7A7AE6, 0xE9ABAB42, 0xBDFEFE43, 0x882A2AA2, 0xD14B4B9A,
0x41010140, 0xC41F1FDB, 0x38E0E0D8, 0xB7D6D661, 0xA18E8E2F, 0xF4DFDF2B,
0xF1CBCB3A, 0xCD3B3BF6, 0xFAE7E71D, 0x608585E5, 0x15545441, 0xA3868625,
0xE3838360, 0xACBABA16, 0x5C757529, 0xA6929234, 0x996E6EF7, 0x34D0D0E4,
0x1A686872, 0x54555501, 0xAFB6B619, 0x914E4EDF, 0x32C8C8FA, 0x30C0C0F0,
0xF6D7D721, 0x8E3232BC, 0xB3C6C675, 0xE08F8F6F, 0x1D747469, 0xF5DBDB2E,
0xE18B8B6A, 0x2EB8B896, 0x800A0A8A, 0x679999FE, 0xC92B2BE2, 0x618181E0,
0xC30303C0, 0x29A4A48D, 0x238C8CAF, 0xA9AEAE07, 0x0D343439, 0x524D4D1F,
0x4F393976, 0x6EBDBDD3, 0xD6575781, 0xD86F6FB7, 0x37DCDCEB, 0x44151551,
0xDD7B7BA6, 0xFEF7F709, 0x8C3A3AB6, 0x2FBCBC93, 0x030C0C0F, 0xFCFFFF03,
0x6BA9A9C2, 0x73C9C9BA, 0x6CB5B5D9, 0x6DB1B1DC, 0x5A6D6D37, 0x50454515,
0x8F3636B9, 0x1B6C6C77, 0xADBEBE13, 0x904A4ADA, 0xB9EEEE57, 0xDE7777A9,
0xBEF2F24C, 0x7EFDFD83, 0x11444455, 0xDA6767BD, 0x5D71712C, 0x40050545,
0x1F7C7C63, 0x10404050, 0x5B696932, 0xDB6363B8, 0x0A282822, 0xC20707C5,
0x31C4C4F5, 0x8A2222A8, 0xA7969631, 0xCE3737F9, 0x7AEDED97, 0xBFF6F649,
0x2DB4B499, 0x75D1D1A4, 0xD3434390, 0x1248485A, 0xBAE2E258, 0xE6979771,
0xB6D2D264, 0xB2C2C270, 0x8B2626AD, 0x68A5A5CD, 0x955E5ECB, 0x4B292962,
0x0C30303C, 0x945A5ACE, 0x76DDDDAB, 0x7FF9F986, 0x649595F1, 0xBBE6E65D,
0xF2C7C735, 0x0924242D, 0xC61717D1, 0x6FB9B9D6, 0xC51B1BDE, 0x86121294,
0x18606078, 0xF3C3C330, 0x7CF5F589, 0xEFB3B35C, 0x3AE8E8D2, 0xDF7373AC,
0x4C353579, 0x208080A0, 0x78E5E59D, 0xEDBBBB56, 0x5E7D7D23, 0x3EF8F8C6,
0xD45F5F8B, 0xC82F2FE7, 0x39E4E4DD, 0x49212168};

static uint32_t rotl(uint32_t a, uint8_t n)
{
return (a << n) | (a >> (32 - n));
}

static uint32_t load_u32_be(const uint8_t *b, uint32_t n)
{
return ((uint32_t)b[4 * n] << 24) |
((uint32_t)b[4 * n + 1] << 16) |
((uint32_t)b[4 * n + 2] << 8) |
((uint32_t)b[4 * n + 3]);
}

static void store_u32_be(uint32_t v, uint8_t *b)
{
b[0] = (uint8_t)(v >> 24);
b[1] = (uint8_t)(v >> 16);
b[2] = (uint8_t)(v >> 8);
b[3] = (uint8_t)(v);
}

static uint32_t SM4_T_non_lin_sub(uint32_t X)
{
uint32_t t = 0;

t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24;
t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16;
t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8;
t |= SM4_S[(uint8_t)X];

return t;
}

static uint32_t SM4_T_slow(uint32_t X)
{
uint32_t t = SM4_T_non_lin_sub(X);

/*
* L linear transform
*/
return t ^ rotl(t, 2) ^ rotl(t, 10) ^ rotl(t, 18) ^ rotl(t, 24);
}

static uint32_t SM4_T(uint32_t X)
{
return SM4_SBOX_T0[(uint8_t)(X >> 24)] ^
SM4_SBOX_T1[(uint8_t)(X >> 16)] ^
SM4_SBOX_T2[(uint8_t)(X >> 8)] ^
SM4_SBOX_T3[(uint8_t)X];
}

static uint32_t SM4_key_sub(uint32_t X)
{
uint32_t t = SM4_T_non_lin_sub(X);

return t ^ rotl(t, 13) ^ rotl(t, 23);
}

int ossl_sm4_set_key(const uint8_t *key, SM4_KEY *ks)
{
/*
* Family Key
*/
static const uint32_t FK[4] = {
0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc};

/*
* Constant Key
*/
static const uint32_t 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};

uint32_t K[4];
int i;

K[0] = load_u32_be(key, 0) ^ FK[0];
K[1] = load_u32_be(key, 1) ^ FK[1];
K[2] = load_u32_be(key, 2) ^ FK[2];
K[3] = load_u32_be(key, 3) ^ FK[3];

for (i = 0; i < SM4_KEY_SCHEDULE; i = i + 4)
{
K[0] ^= SM4_key_sub(K[1] ^ K[2] ^ K[3] ^ CK[i]);
K[1] ^= SM4_key_sub(K[2] ^ K[3] ^ K[0] ^ CK[i + 1]);
K[2] ^= SM4_key_sub(K[3] ^ K[0] ^ K[1] ^ CK[i + 2]);
K[3] ^= SM4_key_sub(K[0] ^ K[1] ^ K[2] ^ CK[i + 3]);
ks->rk[i] = K[0];
ks->rk[i + 1] = K[1];
ks->rk[i + 2] = K[2];
ks->rk[i + 3] = K[3];
}

return 1;
}

#define SM4_RNDS(k0, k1, k2, k3, F) \
do \
{ \
B0 ^= F(B1 ^ B2 ^ B3 ^ ks->rk[k0]); \
B1 ^= F(B0 ^ B2 ^ B3 ^ ks->rk[k1]); \
B2 ^= F(B0 ^ B1 ^ B3 ^ ks->rk[k2]); \
B3 ^= F(B0 ^ B1 ^ B2 ^ ks->rk[k3]); \
} while (0)

void ossl_sm4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks)
{
uint32_t B0 = load_u32_be(in, 0);
uint32_t B1 = load_u32_be(in, 1);
uint32_t B2 = load_u32_be(in, 2);
uint32_t B3 = load_u32_be(in, 3);

/*
* Uses byte-wise sbox in the first and last rounds to provide some
* protection from cache based side channels.
*/
SM4_RNDS(0, 1, 2, 3, SM4_T_slow);
SM4_RNDS(4, 5, 6, 7, SM4_T);
SM4_RNDS(8, 9, 10, 11, SM4_T);
SM4_RNDS(12, 13, 14, 15, SM4_T);
SM4_RNDS(16, 17, 18, 19, SM4_T);
SM4_RNDS(20, 21, 22, 23, SM4_T);
SM4_RNDS(24, 25, 26, 27, SM4_T);
SM4_RNDS(28, 29, 30, 31, SM4_T_slow);

// 这个函数会导致小端 -> 大端,直接内存 dump 密文的没有关系,如果是直接在这里比较密文的话要注意是大端,如果是写进内存比较直接默认比较就行
// 0x666c6167 -> 0x67616c66
store_u32_be(B3, out);
store_u32_be(B2, out + 4);
store_u32_be(B1, out + 8);
store_u32_be(B0, out + 12);
}

void ossl_sm4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks)
{
uint32_t B0 = load_u32_be(in, 0);
uint32_t B1 = load_u32_be(in, 1);
uint32_t B2 = load_u32_be(in, 2);
uint32_t B3 = load_u32_be(in, 3);

SM4_RNDS(31, 30, 29, 28, SM4_T_slow);
SM4_RNDS(27, 26, 25, 24, SM4_T);
SM4_RNDS(23, 22, 21, 20, SM4_T);
SM4_RNDS(19, 18, 17, 16, SM4_T);
SM4_RNDS(15, 14, 13, 12, SM4_T);
SM4_RNDS(11, 10, 9, 8, SM4_T);
SM4_RNDS(7, 6, 5, 4, SM4_T);
SM4_RNDS(3, 2, 1, 0, SM4_T_slow);

// 这个函数会导致小端 -> 大端,直接内存 dump 密文的没有关系,如果是直接在这里比较密文的话要注意是大端,如果是写进内存比较直接默认比较就行
// 0x666c6167 -> 0x67616c66
store_u32_be(B3, out);
store_u32_be(B2, out + 4);
store_u32_be(B1, out + 8);
store_u32_be(B0, out + 12);
}

void printHex(char *name, void *ptr, int len)
{
printf("%s", name);
for (size_t i = 0; i < len; i++)
printf("%02x", ((uint8_t *)ptr)[i]);
printf("\n");
}

void hexdump(char *name, const void *data, size_t size) {
const unsigned char *byte_data = (const unsigned char *)data;
size_t i, j;

printf("%s\n", name);

for (i = 0; i < size; i += 16) {
// 打印偏移地址
printf("%08zx ", i);

// 打印十六进制数据
for (j = 0; j < 16; ++j) {
if (i + j < size) {
printf("%02x ", byte_data[i + j]);
} else {
printf(" "); // 不足部分用空格填充
}

// 在每8字节后添加一个额外的空格
if (j == 7) {
printf(" ");
}
}

printf(" |");

// 打印ASCII字符
for (j = 0; j < 16; ++j) {
if (i + j < size) {
unsigned char ch = byte_data[i + j];
printf("%c", isprint(ch) ? ch : '.');
} else {
printf(" ");
}
}

printf("|\n");
}
}


int main()
{
SM4_KEY *ks = (SM4_KEY *) malloc(sizeof(SM4_KEY));
uint8_t key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
uint8_t input[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
uint8_t output[16];

ossl_sm4_set_key(key, ks);
ossl_sm4_encrypt(input, output, ks);

printHex("Output: ", output, 16);

return 0;
}

DES

标志位修改一下就行了,加解密同源,实际上就是把 sub_key 倒过来

代码1

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
#include<stdio.h>  
#include<string.h>
#include<stdlib.h>
#include"table.h"//存储各种数据表的头文件

// 十六轮子密钥
static bool SubKey[16][48] = { 0 };
/*-----------------------------自定义函数-----------------------------*/
void SetKey(char My_key[8]); //生成16轮的子密钥
void ByteToBit(bool * Data_out, char * Data_in, int Num); //字节转换成位
void BitToByte(char My_message[8], bool * Message_in, int Num); //位转换成字节
void TableReplace(bool *Data_out, bool *Data_in, const char *Table, int Num); //各种表的置换算法
void Bitcopy(bool * Data_out, bool * Data_in, int Num); //二进制数组的拷贝
void Loop_bit(bool * Data_out, int movstep, int len); //左移
void Run_Des(char My_message[8], char CIPhertext[64]);//des的轮加密算法
void Xor(bool * Message_out, bool * Message_in, int Num); //执行异或
void S_change(bool * Data_out, bool * Data_in); // S盒变换
void Run_desDes(char My_message[8], char CIPhertext[64]);// DES轮解密算法
/*--------------------------*/

/*--------------------------主函数----------------------------------*/
int main()
{
int i = 0, j;
char My_key[8] = { 0 }; //记录加密密钥
char You_key[8] = { 0 }; //解密密钥
char My_message[8] = { 0 }; //明文
char CIPhertext[64] = { 0 };//密文
printf("请输入你要加密的内容(8 Byte):\n");
scanf("%s", My_message);
printf("请输入你的加密密钥(8 Byte):\n");
scanf("%s", My_key);
i = strlen(My_key);
while (i != 8)//确保密钥长度为8byte
{
printf("请输入加密密钥(8 Byte)\n");
scanf("%s", My_key);
i = 0;
i = strlen(My_key);
}
SetKey(My_key); //生成16轮的加密子密钥
Run_Des(My_message, CIPhertext); //des的轮加密过程
printf("经过加密的密文为(二进制):\n");
printf("%s", CIPhertext);
printf("\n");
Run_desDes(My_message, CIPhertext);//解密;
printf("解密结果为:\n");
printf("%s", My_message);
printf("\n");
return 0;
}

/*--------------------具体函数定义----------------------*/
void Bitcopy(bool * Data_out, bool * Data_in, int Num) //二进制数组拷贝
{
int i = 0;
for (i = 0; i < Num; i++)
Data_out[i] = Data_in[i];
}
void ByteToBit(bool * Data_out, char * Data_in, int Num) //字节转位,num为二进制位数
{
int i, j;
for (i = 0; i < Num; i++)
Data_out[i] = (Data_in[i / 8] >> (i % 8)) & 0x01;
}
void BitToByte(char My_message[8], bool * Message_in, int Num) //位转换成字节,num为位数
{
int i = 0;
for (i = 0; i < (Num / 8); i++)
My_message[i] = 0;
for (i = 0; i < Num; i++)
My_message[i / 8] |= Message_in[i] << (i % 8);
}
void TableReplace(bool *Data_out, bool * Data_in, const char *Table, int Num) // 置换算法,Num表示置换表的长度
{
int i = 0;
static bool Temp[256] = { 0 };
for (i = 0; i < Num; i++)
{
Temp[i] = Data_in[Table[i] - 1];//将输入数据的指定位置作为输出数据的第i位
}
Bitcopy(Data_out, Temp, Num);
}

void Loop_bit(bool * Data_out, int movstep, int len)//左循环移位
{
static bool Temp[256] = { 0 };
Bitcopy(Temp, Data_out, movstep);//将前movstep位数据放入temp缓存
Bitcopy(Data_out, Data_out + movstep, len - movstep);//数据依次向左移位
Bitcopy(Data_out + len - movstep, Temp, movstep);//将temp中缓存的数据放入最后
}
void Xor(bool * Message_out, bool * Message_in, int Num)//执行异或
{
int i;
for (i = 0; i < Num; i++)
{
Message_out[i] = Message_out[i] ^ Message_in[i];
}
}
void SetKey(char My_key[8])//8字节的初始密钥
{
int i, j;
static bool Key_bit[64] = { 0 }; //Key的二进制缓存
static bool *Key_bit_L, *Key_bit_R;
Key_bit_L = &Key_bit[0]; //key的左边28位
Key_bit_R = &Key_bit[28]; //key的右边28位
ByteToBit(Key_bit, My_key, 64);
TableReplace(Key_bit, Key_bit, PC1_Table, 56);//pc-1 置换
for (i = 0; i < 16; i++)//生成第i个子密钥Subkey[i]
{
Loop_bit(Key_bit_L, Move_Table[i], 28);//左边28位进行左循环移位
Loop_bit(Key_bit_R, Move_Table[i], 28);//右边28位进行左循环移位
TableReplace(SubKey[i], Key_bit, PC2_Table, 48);//pc-2置换
}
}
void S_change(bool * Data_out, bool * Data_in) //S盒变换
{
int i;
int r = 0, c = 0;//S盒的行和列
for (i = 0; i < 8; i++, Data_in = Data_in + 6, Data_out = Data_out + 4) // 每6bit输入进行一次代换
{
r = Data_in[0] * 2 + Data_in[5] * 1;//将m1m6转换为十进制数,作为行数
c = Data_in[1] * 8 + Data_in[2] * 4 + Data_in[3] * 2 + Data_in[4] * 1;//将m2m3m4m5转换为十进制数,作为列数
ByteToBit(Data_out, &S_Box[i][r][c], 4);//取S盒数据,将其二进制形式的每一位填到输出的指定位置
}
}
void F_change(bool Data_out[32], bool Data_in[48]) // f函数
{
int i;
static bool Message_E[48] = { 0 }; //存放E置换的结果
TableReplace(Message_E, Data_out, E_Table, 48);//E表置换
Xor(Message_E, Data_in, 48);//与密钥K[i]异或
S_change(Data_out, Message_E); // S盒变换
TableReplace(Data_out, Data_out, P_Table, 32); //P置换
}
void Run_Des(char My_message[8], char CIPhertext[64])//des轮加密算法
{
int i;
static bool Message_bit[64] = { 0 };
static bool *Message_bit_L = &Message_bit[0], *Message_bit_R = &Message_bit[32];//分成左右两部分,每部分32位
static bool Temp[32] = { 0 };
ByteToBit(Message_bit, My_message, 64);
TableReplace(Message_bit, Message_bit, IP_Table, 64);//初始置换
for (i = 0; i < 16; i++)//每一轮的加密
{
Bitcopy(Temp, Message_bit_R, 32);//缓存右32位
F_change(Message_bit_R, SubKey[i]);//轮函数F
Xor(Message_bit_R, Message_bit_L, 32);//左32位与轮函数F输出进行异或
Bitcopy(Message_bit_L, Temp, 32);//右32位R(i-1)作为下一轮的Li
}
TableReplace(Message_bit, Message_bit, IPR_Table, 64);//逆初始置换
for (i = 0; i < 64;i++)
CIPhertext[i] = Message_bit[i]+'0';//由于是将bool型数据赋给字符型数据,因此要+'0'
CIPhertext[i] = '\0';
}
void Run_desDes(char My_message[8], char CIPhertext[64])// DES轮解密算法
{
int i = 0;
static bool Message_bit[64] = { 0 };
static bool * Message_bit_L = &Message_bit[0], *Message_bit_R = &Message_bit[32];
static bool Temp[32] = { 0 };
for (i = 0; i < 64; i++)
Message_bit[i] = CIPhertext[i]-'0';
TableReplace(Message_bit, Message_bit, IP_Table, 64);
for (i = 15; i >= 0; i--)//与加密过程的区别是子密钥使用顺序相反
{
Bitcopy(Temp, Message_bit_L, 32);
F_change(Message_bit_L, SubKey[i]);
Xor(Message_bit_L, Message_bit_R, 32);
Bitcopy(Message_bit_R, Temp, 32); }
TableReplace(Message_bit, Message_bit, IPR_Table, 64);
BitToByte(My_message, Message_bit, 64);
}
}

代码2

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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
/*
* Data Encryption Standard
* An approach to DES algorithm
*
* By: Daniel Huertas Gonzalez
* Email: huertas.dani@gmail.com
* Version: 0.1
*
* Based on the document FIPS PUB 46-3
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define LB32_MASK 0x00000001
#define LB64_MASK 0x0000000000000001
#define L64_MASK 0x00000000ffffffff
#define H64_MASK 0xffffffff00000000

/* Initial Permutation Table */
static char IP[] = {
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
};

/* Inverse Initial Permutation Table */
static char PI[] = {
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25
};

/*Expansion table */
static char E[] = {
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1
};

/* Post S-Box permutation */
static char P[] = {
16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25
};

/* The S-Box tables */
static char S[8][64] = {{
/* S1 */
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
},{
/* S2 */
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
},{
/* S3 */
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
},{
/* S4 */
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
},{
/* S5 */
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
},{
/* S6 */
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
},{
/* S7 */
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
},{
/* S8 */
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
}};

/* Permuted Choice 1 Table */
static char PC1[] = {
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,

63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
};

/* Permuted Choice 2 Table */
static char PC2[] = {
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
};

/* Iteration Shift Array */
static char iteration_shift[] = {
/* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};

/*
* The DES function
* input: 64 bit message
* key: 64 bit key for encryption/decryption
* mode: 'e' = encryption; 'd' = decryption
*/
uint64_t des(uint64_t input, uint64_t key, char mode) {

int i, j;

/* 8 bits */
char row, column;

/* 28 bits */
uint32_t C = 0;
uint32_t D = 0;

/* 32 bits */
uint32_t L = 0;
uint32_t R = 0;
uint32_t s_output = 0;
uint32_t f_function_res = 0;
uint32_t temp = 0;

/* 48 bits */
uint64_t sub_key[16] = {0};
uint64_t s_input = 0;

/* 56 bits */
uint64_t permuted_choice_1 = 0;
uint64_t permuted_choice_2 = 0;

/* 64 bits */
uint64_t init_perm_res = 0;
uint64_t inv_init_perm_res = 0;
uint64_t pre_output = 0;

/* initial permutation */
for (i = 0; i < 64; i++) {

init_perm_res <<= 1;
init_perm_res |= (input >> (64-IP[i])) & LB64_MASK;

}

L = (uint32_t) (init_perm_res >> 32) & L64_MASK;
R = (uint32_t) init_perm_res & L64_MASK;

/* initial key schedule calculation */
for (i = 0; i < 56; i++) {

permuted_choice_1 <<= 1;
permuted_choice_1 |= (key >> (64-PC1[i])) & LB64_MASK;

}

C = (uint32_t) ((permuted_choice_1 >> 28) & 0x000000000fffffff);
D = (uint32_t) (permuted_choice_1 & 0x000000000fffffff);

/* Calculation of the 16 keys */
for (i = 0; i< 16; i++) {

/* key schedule */
// shifting Ci and Di
for (j = 0; j < iteration_shift[i]; j++) {

C = 0x0fffffff & (C << 1) | 0x00000001 & (C >> 27);
D = 0x0fffffff & (D << 1) | 0x00000001 & (D >> 27);

}

permuted_choice_2 = 0;
permuted_choice_2 = (((uint64_t) C) << 28) | (uint64_t) D ;

sub_key[i] = 0;

for (j = 0; j < 48; j++) {

sub_key[i] <<= 1;
sub_key[i] |= (permuted_choice_2 >> (56-PC2[j])) & LB64_MASK;

}

}

for (i = 0; i < 16; i++) {

/* f(R,k) function */
s_input = 0;

for (j = 0; j< 48; j++) {

s_input <<= 1;
s_input |= (uint64_t) ((R >> (32-E[j])) & LB32_MASK);

}

/*
* Encryption/Decryption
* XORing expanded Ri with Ki
*/
if (mode == 'd') {
// decryption
s_input = s_input ^ sub_key[15-i];

} else {
// encryption
s_input = s_input ^ sub_key[i];

}

/* S-Box Tables */
for (j = 0; j < 8; j++) {
// 00 00 RCCC CR00 00 00 00 00 00 s_input
// 00 00 1000 0100 00 00 00 00 00 row mask
// 00 00 0111 1000 00 00 00 00 00 column mask

row = (char) ((s_input & (0x0000840000000000 >> 6*j)) >> 42-6*j);
row = (row >> 4) | row & 0x01;

column = (char) ((s_input & (0x0000780000000000 >> 6*j)) >> 43-6*j);

s_output <<= 4;
s_output |= (uint32_t) (S[j][16*row + column] & 0x0f);

}

f_function_res = 0;

for (j = 0; j < 32; j++) {

f_function_res <<= 1;
f_function_res |= (s_output >> (32 - P[j])) & LB32_MASK;

}

temp = R;
R = L ^ f_function_res;
L = temp;

}

pre_output = (((uint64_t) R) << 32) | (uint64_t) L;

/* inverse initial permutation */
for (i = 0; i < 64; i++) {

inv_init_perm_res <<= 1;
inv_init_perm_res |= (pre_output >> (64-PI[i])) & LB64_MASK;

}

return inv_init_perm_res;

}

int main(int argc, const char * argv[]) {

int i;

uint64_t input = 0x9474B8E8C73BCA7D;
uint64_t key = 0x0000000000000000;
uint64_t result = input;

/*
* TESTING IMPLEMENTATION OF DES
* Ronald L. Rivest
* X0: 9474B8E8C73BCA7D
* X16: 1B1A2DDB4C642438
*
* OUTPUT:
* E: 8da744e0c94e5e17
* D: 0cdb25e3ba3c6d79
* E: 4784c4ba5006081f
* D: 1cf1fc126f2ef842
* E: e4be250042098d13
* D: 7bfc5dc6adb5797c
* E: 1ab3b4d82082fb28
* D: c1576a14de707097
* E: 739b68cd2e26782a
* D: 2a59f0c464506edb
* E: a5c39d4251f0a81e
* D: 7239ac9a6107ddb1
* E: 070cac8590241233
* D: 78f87b6e3dfecf61
* E: 95ec2578c2c433f0
* D: 1b1a2ddb4c642438 <-- X16
*/
for (i = 0; i < 16; i++) {

if (i%2 == 0) {

result = des(result, result, 'e');
printf ("E: %016llx\n", result);

} else {

result = des(result, result, 'd');
printf ("D: %016llx\n", result);

}
}

//result = des(input, key, 'e');
//printf ("E: %016llx\n", result);

//result = des(result, key, 'd');
//printf ("D: %016llx\n", result);

exit(0);

}

BASE58

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned char* en_base58(unsigned char* input) // 编码
{
static char* nb58 = (char*)"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
size_t len = strlen((char*)input);
size_t rlen = (len / 2 + 1) * 3;
unsigned char* ret = (unsigned char*)malloc(rlen + len);
unsigned char* src = ret + rlen;
unsigned char* rptr = ret + rlen;
unsigned char* ptr, * e = src + len - 1;
size_t i;
memcpy(src, input, len);
while (src <= e)
{
if (*src)
{
unsigned char rest = 0;
ptr = src;
while (ptr <= e)
{
unsigned int c = rest * 256;
rest = (c + *ptr) % 58;
*ptr = (c + *ptr) / 58;
ptr++;
}
--rptr;
*rptr = nb58[rest];
}
else
{
src++;
}
}
for (i = 0; i < ret + rlen - rptr; i++)
ret[i] = rptr[i];
ret[i] = 0;
return ret;
}

bool de_base58(unsigned char* src) // 解码
{
static char b58n[] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1,
-1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19, 20, 21, -1,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1,
-1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46,
47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
size_t len = strlen((char*)src);
size_t rlen = (len / 4 + 1) * 3;
unsigned char* ret = (unsigned char*)malloc(rlen);
unsigned char* rptr = ret + rlen;
size_t i;
unsigned char* ptr;
for (i = 0; i < len; i++)
{
char rest = b58n[src[i]];
if (rest < 0)
{
free(ret);
return NULL;
}
for (ptr = ret + rlen - 1; ptr >= rptr; ptr--)
{
unsigned int c = rest + *ptr * 58;
*ptr = c % 256;
rest = c / 256;
}
if (rest > 0)
{
rptr--;
if (rptr < ret)
{
free(ret);
return NULL;
}
*rptr = rest;
}
}
for (i = 0; i < ret + rlen - rptr; i++)
ret[i] = rptr[i];
ret[i] = 0;
memcpy(src, ret, strlen((char*)src));
}

int main()
{
char str[] = "9EGJCxbxRGT";
printf("%s\n", en_base58((unsigned char*)"12345678"));
de_base58((unsigned char*)str);
printf("%s", str);
getchar();
return 0;
}

SHA1

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
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define rol(x,y) ((x<<y)|(x>>(32-y))) //循环左移

//一次循环过程,str为填充后的数据或是数据中的一部分
void round(unsigned char str[64],unsigned int h[5]){
unsigned int a, b, c, d, e,tmp,w[80];
unsigned int i;
for(i=0;i<16;i++){
w[i]=((unsigned int)str[i*4]<<24)|(((unsigned int)str[i*4+1])<<16)|
(((unsigned int)str[i*4+2])<<8)|(((unsigned int)str[i*4+3])<<0);
}
for (i=16;i<80;i++ ){
tmp = w[i-3]^w[i-8]^w[i-14]^w[i-16];
w[i]=rol(tmp,1);
}

a=h[0];b=h[1];c=h[2];d=h[3];e=h[4];
for(i=0;i<80;i++){
switch(i/20){
case 0:tmp=rol(a,5)+((b&c)|(d&~b))+e+w[i]+0x5a827999;break;
case 1:tmp=rol(a,5)+(b^c^d)+e+w[i]+0x6ed9eba1;break;
case 2:tmp=rol(a,5)+((b&c)|(b&d)|(c&d))+e+w[i] +0x8f1bbcdc;break;
case 3:tmp=rol(a,5)+(b^c^d)+e+w[i] + 0xca62c1d6;break;
}
e=d;d=c;
c=rol(b,30);
b=a;a=tmp;
}
h[0]+=a;h[1]+=b;h[2]+=c;h[3]+=d;h[4]+=e;
}

//sha-1算法
void sha1(unsigned char*input,long long len,unsigned char*output){
unsigned char temp[64];
unsigned int h[5]={0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0};
unsigned int i,n=len,tmp;
while(n>=64){
memcpy(temp,input+len-n,64);
round(temp,h);
n-=64;
}

if(n>=56){
memset(temp,0,64);
memcpy(temp,input+len-n,n);temp[n]=128;
round(temp,h);
memset(temp,0,64);
for(i=56;i<64;i++)
temp[i]=((len*8)>>(63-i)*8)&0xff;
round(temp,h);
}
else{
memset(temp,0,64);
memcpy(temp,input+len-n,n);temp[n]=128;
for(i=56;i<64;i++)
temp[i]=((len*8)>>(63-i)*8)&0xff;
round(temp,h);
}

for(i=0;i<20;i++){
tmp=(h[i/4]>>((3-i%4)*8))&0xff;
sprintf((char*)output+2*i,"%02x",tmp);
}
}

//测试
int main(){
unsigned char input[]="this is a test aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",output[40]={0};
sha1(input,strlen((char*)input),output);
printf("%s\n",output);
}


CRC32

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
/* crc32.c
Copyright (C) 2009-2024 Free Software Foundation, Inc.

This file is part of the libiberty library.

This file is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file. (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combined
executable.)

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "libiberty.h"

/* This table was generated by the following program.

#include <stdio.h>

int
main ()
{
unsigned int i, j;
unsigned int c;
int table[256];

for (i = 0; i < 256; i++)
{
for (c = i << 24, j = 8; j > 0; --j)
c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
table[i] = c;
}

printf ("static const unsigned int crc32_table[] =\n{\n");
for (i = 0; i < 256; i += 4)
{
printf (" 0x%08x, 0x%08x, 0x%08x, 0x%08x",
table[i + 0], table[i + 1], table[i + 2], table[i + 3]);
if (i + 4 < 256)
putchar (',');
putchar ('\n');
}
printf ("};\n");
return 0;
}

For more information on CRC, see, e.g.,
http://www.ross.net/crc/download/crc_v3.txt. */

static const unsigned int crc32_table[] =
{
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};

/*

@deftypefn Extension {unsigned int} crc32 (const unsigned char *@var{buf}, @
int @var{len}, unsigned int @var{init})

Compute the 32-bit CRC of @var{buf} which has length @var{len}. The
starting value is @var{init}; this may be used to compute the CRC of
data split across multiple buffers by passing the return value of each
call as the @var{init} parameter of the next.

This is used by the @command{gdb} remote protocol for the @samp{qCRC}
command. In order to get the same results as gdb for a block of data,
you must pass the first CRC parameter as @code{0xffffffff}.

This CRC can be specified as:

Width : 32
Poly : 0x04c11db7
Init : parameter, typically 0xffffffff
RefIn : false
RefOut : false
XorOut : 0

This differs from the "standard" CRC-32 algorithm in that the values
are not reflected, and there is no final XOR value. These differences
make it easy to compose the values of multiple blocks.

@end deftypefn

*/

unsigned int
xcrc32 (const unsigned char *buf, int len, unsigned int init)
{
unsigned int crc = init;
while (len--)
{
crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
buf++;
}
return crc;
}

MD5

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
248
249
250
251
252
253
/*
* Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
* and modified slightly to be functionally identical but condensed into control structures.
*/

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

typedef struct{
uint64_t size; // Size of input in bytes
uint32_t buffer[4]; // Current accumulation of hash
uint8_t input[64]; // Input to be used in the next step
uint8_t digest[16]; // Result of algorithm
} MD5Context;

/*
* Constants defined by the MD5 algorithm
*/
#define A 0x67452301
#define B 0xefcdab89
#define C 0x98badcfe
#define D 0x10325476

static uint32_t S[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};

static uint32_t K[] = {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};

/*
* Padding used to make the size (in bits) of the input congruent to 448 mod 512
*/
static uint8_t PADDING[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

/*
* Bit-manipulation functions defined by the MD5 algorithm
*/
#define F(X, Y, Z) ((X & Y) | (~X & Z))
#define G(X, Y, Z) ((X & Z) | (Y & ~Z))
#define H(X, Y, Z) (X ^ Y ^ Z)
#define I(X, Y, Z) (Y ^ (X | ~Z))

/*
* Rotates a 32-bit word left by n bits
*/
uint32_t rotateLeft(uint32_t x, uint32_t n){
return (x << n) | (x >> (32 - n));
}


/*
* Initialize a context
*/
void md5Init(MD5Context *ctx){
ctx->size = (uint64_t)0;

ctx->buffer[0] = (uint32_t)A;
ctx->buffer[1] = (uint32_t)B;
ctx->buffer[2] = (uint32_t)C;
ctx->buffer[3] = (uint32_t)D;
}

/*
* Add some amount of input to the context
*
* If the input fills out a block of 512 bits, apply the algorithm (md5Step)
* and save the result in the buffer. Also updates the overall size.
*/
void md5Update(MD5Context *ctx, uint8_t *input_buffer, size_t input_len){
uint32_t input[16];
unsigned int offset = ctx->size % 64;
ctx->size += (uint64_t)input_len;

// Copy each byte in input_buffer into the next space in our context input
for(unsigned int i = 0; i < input_len; ++i){
ctx->input[offset++] = (uint8_t)*(input_buffer + i);

// If we've filled our context input, copy it into our local array input
// then reset the offset to 0 and fill in a new buffer.
// Every time we fill out a chunk, we run it through the algorithm
// to enable some back and forth between cpu and i/o
if(offset % 64 == 0){
for(unsigned int j = 0; j < 16; ++j){
// Convert to little-endian
// The local variable `input` our 512-bit chunk separated into 32-bit words
// we can use in calculations
input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 |
(uint32_t)(ctx->input[(j * 4) + 2]) << 16 |
(uint32_t)(ctx->input[(j * 4) + 1]) << 8 |
(uint32_t)(ctx->input[(j * 4)]);
}
md5Step(ctx->buffer, input);
offset = 0;
}
}
}

/*
* Pad the current input to get to 448 bytes, append the size in bits to the very end,
* and save the result of the final iteration into digest.
*/
void md5Finalize(MD5Context *ctx){
uint32_t input[16];
unsigned int offset = ctx->size % 64;
unsigned int padding_length = offset < 56 ? 56 - offset : (56 + 64) - offset;

// Fill in the padding and undo the changes to size that resulted from the update
md5Update(ctx, PADDING, padding_length);
ctx->size -= (uint64_t)padding_length;

// Do a final update (internal to this function)
// Last two 32-bit words are the two halves of the size (converted from bytes to bits)
for(unsigned int j = 0; j < 14; ++j){
input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 |
(uint32_t)(ctx->input[(j * 4) + 2]) << 16 |
(uint32_t)(ctx->input[(j * 4) + 1]) << 8 |
(uint32_t)(ctx->input[(j * 4)]);
}
input[14] = (uint32_t)(ctx->size * 8);
input[15] = (uint32_t)((ctx->size * 8) >> 32);

md5Step(ctx->buffer, input);

// Move the result into digest (convert from little-endian)
for(unsigned int i = 0; i < 4; ++i){
ctx->digest[(i * 4) + 0] = (uint8_t)((ctx->buffer[i] & 0x000000FF));
ctx->digest[(i * 4) + 1] = (uint8_t)((ctx->buffer[i] & 0x0000FF00) >> 8);
ctx->digest[(i * 4) + 2] = (uint8_t)((ctx->buffer[i] & 0x00FF0000) >> 16);
ctx->digest[(i * 4) + 3] = (uint8_t)((ctx->buffer[i] & 0xFF000000) >> 24);
}
}

/*
* Step on 512 bits of input with the main MD5 algorithm.
*/
void md5Step(uint32_t *buffer, uint32_t *input){
uint32_t AA = buffer[0];
uint32_t BB = buffer[1];
uint32_t CC = buffer[2];
uint32_t DD = buffer[3];

uint32_t E;

unsigned int j;

for(unsigned int i = 0; i < 64; ++i){
switch(i / 16){
case 0:
E = F(BB, CC, DD);
j = i;
break;
case 1:
E = G(BB, CC, DD);
j = ((i * 5) + 1) % 16;
break;
case 2:
E = H(BB, CC, DD);
j = ((i * 3) + 5) % 16;
break;
default:
E = I(BB, CC, DD);
j = (i * 7) % 16;
break;
}

uint32_t temp = DD;
DD = CC;
CC = BB;
BB = BB + rotateLeft(AA + E + K[i] + input[j], S[i]);
AA = temp;
}

buffer[0] += AA;
buffer[1] += BB;
buffer[2] += CC;
buffer[3] += DD;
}

/*
* Functions that run the algorithm on the provided input and put the digest into result.
* result should be able to store 16 bytes.
*/
void md5String(char *input, uint8_t *result){
MD5Context ctx;
md5Init(&ctx);
md5Update(&ctx, (uint8_t *)input, strlen(input));
md5Finalize(&ctx);

memcpy(result, ctx.digest, 16);
}

void md5File(FILE *file, uint8_t *result){
char *input_buffer = malloc(1024);
size_t input_size = 0;

MD5Context ctx;
md5Init(&ctx);

while((input_size = fread(input_buffer, 1, 1024, file)) > 0){
md5Update(&ctx, (uint8_t *)input_buffer, input_size);
}

md5Finalize(&ctx);

free(input_buffer);

memcpy(result, ctx.digest, 16);
}

void print_hash(uint8_t *p){
for(unsigned int i = 0; i < 16; ++i){
printf("%02x", p[i]);
}
printf("\n");
}

int main(int argc, char *argv[]){
uint8_t result[16];
if(argc > 1){
for(int i = 1; i < argc; ++i){
md5String(argv[i], result);
print_hash(result);
}
} else{
md5File(stdin, result);
print_hash(result);
}
}

RC4

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
#include<stdio.h> 
#include<stdlib.h>
#include<string.h>

//s表的长度取256
#define size 256

unsigned char sbox[257]={0};

//初始化s表
void init_sbox(unsigned char*key){
unsigned int i,j,k;
int tmp;

for(i=0;i<size;i++){
sbox[i]=i;
}

j=k=0;
for(i=0;i<size;i++){
tmp=sbox[i];
j=(j+tmp+key[k])%size;
sbox[i]=sbox[j];
sbox[j]=tmp;
if(++k>=strlen((char*)key))k=0;
}
}

//加解密函数
void enc_dec(unsigned char*key,unsigned char*data){
int i,j,k,R,tmp;

init_sbox(key);

j=k=0;
for(i=0;i<strlen((char*)data);i++){
j=(j+1)%size;
k=(k+sbox[j])%size;

tmp=sbox[j];
sbox[j]=sbox[k];
sbox[k]=tmp;

R=sbox[(sbox[j]+sbox[k])%size];

data[i]^=R;
}
}

int main(){
unsigned char key[100]={0};
unsigned char data[100]={0};
printf("输入你要加密的字符:");
scanf("%100s",data);
printf("输入密钥:");
scanf("%40s",key);
enc_dec(key,data);
printf("enc: %s\n",data);
enc_dec(key,data);
printf("dec: %s\n",data);
return 0;
}

参考链接

Pangbai.work [常见加密解密算法]

mengsuenyan [AES加密算法]

枫のBlog 密码学——AES/DES加密算法原理介绍

gcc-mirror c3c

Zunawe MD5

windard SM4

dhuertas DES

lmshao AES

侵权请联系删除

 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
本站由 提供部署服务
访客数 访问量