IDEA加密流程

国际数据加密算法 (International Data Encryption Algorithm,IDEA) 是最强大的加密算法之一。

IDEA的明文长度为 64 位,而密钥长度为 128 位。

IDEA 加密流程:

IDEA框图

IDEA 每轮的加密过程:

IDEAround

末轮后的输出变换:

输出变换

IDEA 密钥的产生:

CreateKey

代码部分:

1
2
3
4
5
6
7
8
9
10
11
#include<iostream>
#include<bitset>
#include<math.h>
using namespace std;
//定义简单的别名
typedef bitset<16> code; //16位
typedef bitset<128> key; //128位秘钥
//定义一些变量
bitset<16> sub_key[52]; //52个子秘钥
bitset<16> inv_sub_key[52]; //52个逆子秘钥
bitset<64> plaint_txt;

异或运算

1
2
3
4
code XOR(code code_1, code code_2)
{
return code_1 ^ code_2;
}

加法运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

code Plus(code code_1, code code_2)
{
int tmp = 0;
code result;
for (int i = 0; i < 16; i++) //二进制转换成十进制
{
tmp += code_1[i] * pow(2, i) + code_2[i] * pow(2, i);
}
tmp %= 65536;
bitset<16> binary(tmp); //转换成二进制
for (int i = 0; i < 16; i++)
result[i] = binary[i];

return result;
}

逆加法

1
2
3
4
5
6
7
8
9
10
11
12
13
14

code invPlus(code code_in)
{
int tmp = 0;
code result;
for (int i = 0; i < 16; i++) //二进制转换成十进制
tmp += code_in[i] * pow(2, i);
tmp = 65536 - tmp;
bitset<16> binary(tmp); //转换成二进制
for (int i = 0; i < 16; i++)
result[i] = binary[i];

return result;
}

乘法运算

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

code Times(code code_1, code code_2)
{
code result;
long long tmp;
long long tmp_1 = 0, tmp_2 = 0;
for (int i = 0; i < 16; i++) //二进制转换成十进制
{
tmp_1 += code_1[i] * pow(2, i);
tmp_2 += code_2[i] * pow(2, i);
}
if (code_1 == 0)
tmp_1 = 65536;
if (code_2 == 0)
tmp_2 = 65536;

tmp = (tmp_1 * tmp_2) % 65537;
if (tmp == 65536) //如果得到最大值即等价于0x0000
result = 0x0000;
else
{
bitset<16> binary(tmp); //转换成二进制
for (int i = 0; i < 16; i++)
result[i] = binary[i];
}
return result;
}

拓展欧几里得算法

1
2
3
4
5
6
7
void Exgcd(int a, int b, int& x, int& y) 
{
if (!b)
x = 1, y = 0;
else
Exgcd(b, a % b, y, x), y -= a / b * x;
}

利用欧几里得扩展算法求乘法的逆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

code invTimes(code code_in)
{
code result;
int tmp = 0;
for (int i = 0; i < 16; i++) //首先转换成十进制
tmp += code_in[i] * pow(2, i);

int x, y;
int p = 65537;
Exgcd(tmp, p, x, y);
x = (x % p + p) % p; //x即为tmp在 (mod65537) 的乘法逆
bitset<16> binary(x); //转换成二进制
for (int j = 0; j < 16; j++)
result[j] = binary[j];

return result;
}

全部代码:

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
#include<iostream>
#include<bitset>
#include<math.h>
using namespace std;
typedef bitset<16> code; //16位
typedef bitset<128> key; //128位秘钥

bitset<16> sub_key[52]; //52个子秘钥
bitset<16> inv_sub_key[52]; //52个逆子秘钥
bitset<64> plaint_txt;

//异或运算
code XOR(code code_1, code code_2)
{
return code_1 ^ code_2;
}

//加法运算
code Plus(code code_1, code code_2)
{
int tmp = 0;
code result;
for (int i = 0; i < 16; i++) //二进制转换成十进制
{
tmp += code_1[i] * pow(2, i) + code_2[i] * pow(2, i);
}
tmp %= 65536;
bitset<16> binary(tmp); //转换成二进制
for (int i = 0; i < 16; i++)
result[i] = binary[i];

return result;
}

//逆加法
code invPlus(code code_in)
{
int tmp = 0;
code result;
for (int i = 0; i < 16; i++) //二进制转换成十进制
tmp += code_in[i] * pow(2, i);
tmp = 65536 - tmp;
bitset<16> binary(tmp); //转换成二进制
for (int i = 0; i < 16; i++)
result[i] = binary[i];

return result;

}
//乘法运算
code Times(code code_1, code code_2)
{
code result;
long long tmp;
long long tmp_1 = 0, tmp_2 = 0;
for (int i = 0; i < 16; i++) //二进制转换成十进制
{
tmp_1 += code_1[i] * pow(2, i);
tmp_2 += code_2[i] * pow(2, i);
}
if (code_1 == 0)
tmp_1 = 65536;
if (code_2 == 0)
tmp_2 = 65536;

tmp = (tmp_1 * tmp_2) % 65537;
if (tmp == 65536) //如果得到最大值即等价于0x0000
result = 0x0000;
else
{
bitset<16> binary(tmp); //转换成二进制
for (int i = 0; i < 16; i++)
result[i] = binary[i];
}
return result;
}

void Exgcd(int a, int b, int& x, int& y) //拓展欧几里得算法
{
if (!b)
x = 1, y = 0;
else
Exgcd(b, a % b, y, x), y -= a / b * x;
}
//利用欧几里得扩展算法求乘法的逆
code invTimes(code code_in)
{
code result;
int tmp = 0;
for (int i = 0; i < 16; i++) //首先转换成十进制
tmp += code_in[i] * pow(2, i);

int x, y;
int p = 65537;
Exgcd(tmp, p, x, y);
x = (x % p + p) % p; //x即为tmp在 (mod65537) 的乘法逆
bitset<16> binary(x); //转换成二进制
for (int j = 0; j < 16; j++)
result[j] = binary[j];

return result;
}
//子秘钥生成
void subkeys_get(code keys_input[8])//输入8个16bit组
{
key keys;
for (int i = 0; i < 8; i++) //转化成128位
{
for (int j = 0; j < 16; j++)
{
keys[j + 16 * i] = keys_input[7 - i][j];
}
}
for (int i = 0; i < 8; i++) //前8个子秘钥(不移动)
{
for (int j = 0; j < 16; j++)
sub_key[i][15 - j] = keys[127 - (j + 16 * i)];
}
for (int i = 0; i < 5; i++) //中间40个子秘钥()每次循环左移25位
{
key tmp_keys = keys >> 103;
keys = (keys << 25) | (tmp_keys);
for (int j = (8 + 8 * i); j < (8 * (i + 2)); j++)
{
for (int k = 0; k < 16; k++)
sub_key[j][15 - k] = keys[127 - (k + 16 * (j - 8 - 8 * i))];
}
}
key tmp_keys = keys >> 103; //最后一次循环左移取前四个
keys = (keys << 25) | (tmp_keys);
for (int i = 48; i < 52; i++)
{
for (int j = 0; j < 16; j++)
sub_key[i][15 - j] = keys[127 - (j + 16 * (i - 48))];
}
}
void inv_subkeys_get(code sub_key[52]) //将52个子秘钥调用
{
//生成逆子秘钥
for (int i = 6; i < 48; i = i + 6) //U_1, U_2, U_3, U_4 (2 <= i <= 8)
{
inv_sub_key[i] = invTimes(sub_key[48 - i]);
inv_sub_key[i + 1] = invPlus(sub_key[50 - i]);
inv_sub_key[i + 2] = invPlus(sub_key[49 - i]);
inv_sub_key[i + 3] = invTimes(sub_key[51 - i]);
}
for (int i = 0; i < 48; i = i + 6) //U_5, U_6 (1 <= i <= 8)
{
inv_sub_key[i + 4] = sub_key[46 - i];
inv_sub_key[i + 5] = sub_key[47 - i];
}
//U_1, U_2, U_3, U_4 (i = 1, 9)
inv_sub_key[0] = invTimes(sub_key[48]);
inv_sub_key[1] = invPlus(sub_key[49]);
inv_sub_key[2] = invPlus(sub_key[50]);
inv_sub_key[3] = invTimes(sub_key[51]);

inv_sub_key[48] = invTimes(sub_key[0]);
inv_sub_key[49] = invPlus(sub_key[1]);
inv_sub_key[50] = invPlus(sub_key[2]);
inv_sub_key[51] = invTimes(sub_key[3]);

}
//加密
bitset<64> encrypt(bitset<64> plaint)
{
bitset<16> I_1, I_2, I_3, I_4;
bitset<64> cipher;
for (int i = 0; i < 16; i++) //明文分成4个16位(I_1, I_2, I_3, I_4)
{
I_1[15 - i] = plaint[63 - i];
I_2[15 - i] = plaint[47 - i];
I_3[15 - i] = plaint[31 - i];
I_4[15 - i] = plaint[15 - i];
}
for (int i = 0, j = 1; i < 48, j <= 8; i = i + 6, j++) //轮结构运算
{
bitset<16> tmp_1 = Times(sub_key[i], I_1);
bitset<16> tmp_2 = Plus(sub_key[i + 1], I_2);
bitset<16> tmp_3 = Plus(sub_key[i + 2], I_3);
bitset<16> tmp_4 = Times(sub_key[i + 3], I_4);
bitset<16> tmp_5 = XOR(tmp_1, tmp_3);
bitset<16> tmp_6 = XOR(tmp_2, tmp_4);
bitset<16> tmp_7 = Times(sub_key[i + 4], tmp_5);
bitset<16> tmp_8 = Plus(tmp_6, tmp_7);
bitset<16> tmp_9 = Times(tmp_8, sub_key[i + 5]);
bitset<16> tmp_10 = Plus(tmp_7, tmp_9);
I_1 = XOR(tmp_1, tmp_9);
I_2 = XOR(tmp_3, tmp_9);
I_3 = XOR(tmp_2, tmp_10);
I_4 = XOR(tmp_4, tmp_10);
//cout << "第" << j << "轮tmp_1: " << tmp_1 << endl;
//cout << "第" << j << "轮tmp_2: " << tmp_2 << endl;
//cout << "第" << j << "轮tmp_3: " << tmp_3 << endl;
//cout << "第" << j << "轮tmp_4: " << tmp_4 << endl;
//cout << "第" << j << "轮tmp_5: " << tmp_5 << endl;
//cout << "第" << j << "轮tmp_6: " << tmp_6 << endl;
//cout << "第" << j << "轮tmp_7: " << tmp_7 << endl;
//cout << "第" << j << "轮tmp_8: " << tmp_8 << endl;
//cout << "第" << j << "轮tmp_9: " << tmp_9 << endl;
//cout << "第" << j << "轮tmp_10:" << tmp_10 << endl;
//cout << "第" << j << "轮I_1: " << I_1 << endl;
//cout << "第" << j << "轮I_2: " << I_2 << endl;
//cout << "第" << j << "轮I_3: " << I_3 << endl;
//cout << "第" << j << "轮I_4: " << I_4 << endl;
//cout << endl;
}
//输出变换
bitset<16> Y_1 = Times(I_1, sub_key[48]);
bitset<16> Y_2 = Plus(I_3, sub_key[49]);
bitset<16> Y_3 = Plus(I_2, sub_key[50]);
bitset<16> Y_4 = Times(I_4, sub_key[51]);
cout << endl;
cout << "输出变换Y_1:" << Y_1 << endl;
cout << "输出变换Y_2:" << Y_2 << endl;
cout << "输出变换Y_3:" << Y_3 << endl;
cout << "输出变换Y_4:" << Y_4 << endl;
cout << endl;

for (int i = 0; i < 16; i++) //整合4个输出成密文
{
cipher[i] = Y_4[i];
cipher[i + 16] = Y_3[i];
cipher[i + 32] = Y_2[i];
cipher[i + 48] = Y_1[i];
}
return cipher;
}
//解密(过程与加密一致,子秘钥变成逆子秘钥)
bitset<64> dencrypt(bitset<64> cipher)
{
//解密
bitset<16> I_1, I_2, I_3, I_4;
bitset<64> plaint;
for (int i = 0; i < 16; i++)
{
I_1[15 - i] = cipher[63 - i];
I_2[15 - i] = cipher[47 - i];
I_3[15 - i] = cipher[31 - i];
I_4[i] = cipher[i];
}
for (int i = 0; i < 48; i = i + 6)
{
bitset<16> tmp_1 = Times(inv_sub_key[i], I_1);
bitset<16> tmp_2 = Plus(inv_sub_key[i + 1], I_2);
bitset<16> tmp_3 = Plus(inv_sub_key[i + 2], I_3);
bitset<16> tmp_4 = Times(inv_sub_key[i + 3], I_4);
bitset<16> tmp_5 = XOR(tmp_1, tmp_3);
bitset<16> tmp_6 = XOR(tmp_2, tmp_4);
bitset<16> tmp_7 = Times(inv_sub_key[i + 4], tmp_5);
bitset<16> tmp_8 = Plus(tmp_6, tmp_7);
bitset<16> tmp_9 = Times(tmp_8, inv_sub_key[i + 5]);
bitset<16> tmp_10 = Plus(tmp_7, tmp_9);
I_1 = XOR(tmp_1, tmp_9);
I_2 = XOR(tmp_3, tmp_9);
I_3 = XOR(tmp_2, tmp_10);
I_4 = XOR(tmp_4, tmp_10);
}
bitset<16> Y_1 = Times(I_1, inv_sub_key[48]);
bitset<16> Y_2 = Plus(I_3, inv_sub_key[49]);
bitset<16> Y_3 = Plus(I_2, inv_sub_key[50]);
bitset<16> Y_4 = Times(I_4, inv_sub_key[51]);

for (int i = 0; i < 16; i++)
{
plaint[i] = Y_4[i];
plaint[i + 16] = Y_3[i];
plaint[i + 32] = Y_2[i];
plaint[i + 48] = Y_1[i];
}
return plaint;

}
int main()
{
plaint_txt = 0xa6224adf2f28df73;//64位明文
//plaint_txt = 0xa79587231f2c6d73 ;
cout << "明文:" << endl << plaint_txt << endl;
code keys_input[8] = { 0xada1, 0x048b, 0x71a1, 0xf9c7, 0x5266, 0xbfd6, 0x24a2, 0xdff1 };//128位秘钥

subkeys_get(keys_input); //生成子秘钥
inv_subkeys_get(sub_key);//生成逆子秘钥

cout << "\n*轮结构运算过程在注释状态,可关闭注释展示*\n" << endl;

bitset<64> cipher = encrypt(plaint_txt); //加密得到密文cipher
cout << "加密得到的密文为:" << endl << cipher << endl;

bitset<64> plaint = dencrypt(cipher); //解密得到明文plaint
cout << "解密密文为:" << endl << plaint << endl;

return 0;
}

运行结果:

output