Simplified Data Encryption Standard S-DES 是一个供教学的非安全的加密算法,它与DES的特性和结构类似,但参数小,明文分组为8位,主密钥分组为10位,采用两轮迭代。
1 #include <cstdio>
2 #include <iostream>
3 #include <fstream>
4 #include <algorithm>
5 #include <vector>
6 #include <string>
7
8 class S_DES {
9 private:
10 typedef unsigned int uint;
11 typedef unsigned char uchar;
12 typedef std::pair<unsigned int, unsigned int> PII;
13 typedef std::pair<PII, PII> PPI;
14 typedef std::vector<unsigned int> VI;
15 typedef std::vector<VI> VVI;
16 typedef std::vector<unsigned char> VC;
17 typedef std::string String;
18
19 const static VI P_10;
20 const static VI P_8;
21 const static VI P_4;
22 const static VI IP;
23 const static VI IP_1;
24 const static VI EP;
25 const static VVI S_1;
26 const static VVI S_2;
27
28 // MakePII
29 inline PII MakePII(uint L, uint R) {
30 return std::make_pair(L, R);
31 }
32
33 // MakePPI
34 inline PPI MakePPI(uint A, uint B, uint C, uint D) {
35 return std::make_pair(std::make_pair(A, B), std::make_pair(C, D));
36 }
37
38 // 置换,长度为X
39 uint Permutation(uint Bit, int X, const VI &P) {
40 uint res = 0;
41 int n = P.size();
42 for (int i = 0; i < n; i++) {
43 res <<= 1;
44 if (Bit & (1 << (X - P[i]))) res |= 1;
45 }
46 return res;
47 }
48
49 // 逆置换
50 uint InversePermutation(uint Bit, int X, const VI &P) {
51 uint res = 0;
52 int n = P.size();
53 for (int i = 0; i < n; i++) {
54 if (Bit&(1 << (n - i - 1))) {
55 res |= 1 << (X - P[i]);
56 }
57 }
58 return res;
59 }
60
61 // 以X为单位分割二进制数为两份
62 PII Split(uint Bit, int X) {
63 uint L = 0, R = 0;
64 uint mask = (1 << X) - 1;
65 R = Bit & mask;
66 L = Bit >> X;
67 return MakePII(L, R);
68 }
69
70 // 将四位二进制数转化为S-BOX的坐标
71 PII GetBoxXY(uint Bit) {
72 uint x = 0, y = 0;
73 if (Bit&(1 << 3)) x |= 1;
74 if (Bit&(1 << 2)) y |= 1;
75 x <<= 1;
76 y <<= 1;
77 if (Bit&(1 << 0)) x |= 1;
78 if (Bit&(1 << 1)) y |= 1;
79 return MakePII(x, y);
80 }
81
82 // 将八位二进制数转化为S-BOX的坐标
83 PPI GetExBox(uint Bit) {
84 PII pii = Split(Bit,4);
85 PII xy1 = GetBoxXY(pii.first);
86 PII xy2 = GetBoxXY(pii.second);
87 return MakePPI(xy1.first, xy1.second, xy2.first, xy2.second);
88 }
89
90 // 合并两个长度为X的二进制数
91 uint Merge(uint lBit, uint rBit, int X) {
92 return (lBit << X) | rBit;
93 }
94
95 // 将长度为L的二进制数,循环左移X次
96 uint LS(uint Bit, int L, int X) {
97 X %= L;
98 uint mask = (1 << L) - 1;
99 uint ans = ((Bit << X) & mask) | (Bit >> (L - X));
100 return ans;
101 }
102
103 // S-DES 子密码生成过程,MasterKey是10位的主密钥。
104 PII GetSubPsw(uint MasterKey) {
105 uint K = Permutation(MasterKey, 10, P_10);// 主密钥K进行P10置换
106 PII pii = Split(K, 5); // 分成左5位右5位
107 uint L = pii.first; //
108 uint R = pii.second; //
109 L = LS(L, 5, 1); // 分别进行LS-1操作
110 R = LS(R, 5, 1); // 其结果一方面作为下一轮的初始值
111 uint K_1 = Merge(L, R, 5); // 另一方面进行P8置换
112 K_1 = Permutation(K_1, 10, P_8); // 得到K1
113 L = LS(L, 5, 2); // 再分别左循环2位
114 R = LS(R, 5, 2); //
115 uint K_2 = Merge(L, R, 5); //
116 K_2 = Permutation(K_2, 10, P_8); // 经过P8置换,得到K2
117 return MakePII(K_1, K_2);
118 }
119
120 // S-DES的f函数
121 uint Function(uint Ipt, uint K) {
122 uint ex = Permutation(Ipt, 4, EP);// E/P扩展及置换。将4位R扩展为8位
123 ex ^= K; // 扩展后的8位异或秘钥K
124 PPI ppi = GetExBox(ex); // 左边4位作为S1盒输入,右边四位作为S2盒输入
125 uint x1 = ppi.first.first; // 在S1和S2中,第一位与第四位结合形成2位代表S盒的行号
126 uint y1 = ppi.first.second; // 第二位与第三位结合形成2位代表S盒的列号
127 uint x2 = ppi.second.first; //
128 uint y2 = ppi.second.second; //
129 uint s1 = S_1[x1][y1]; // 得到S盒的输出
130 uint s2 = S_2[x2][y2]; //
131 uint res = Merge(s1, s2, 2); //
132 res = Permutation(res, 4, P_4); // 进行P4置换,得到f函数的输出
133 return res;
134 }
135
136 // S-DES 加密
137 uint S_DES_Main(uint Plaintext, uint K_1, uint K_2) {
138 Plaintext = Permutation(Plaintext, 8, IP);// 初始置换IP,将8位明文按照置换顺序进行位置变化。
139 PII pii = Split(Plaintext, 4); // 置换后分
140 uint L0 = pii.first; // 左4位L0
141 uint R0 = pii.second; // 右4位R0
142 uint L1 = R0; // 第一轮运算,R0作为下一轮的L1
143 uint R1 = L0 ^ (Function(R0, K_1)); // R0作为f函数的输入与8位子秘钥K1参与函数运算,运算结构与L0异或,结果作为下一轮的R1
144 uint R2 = R1; // 第二轮运算,R1作为下一轮的R2
145 uint L2 = L1 ^ (Function(R1, K_2)); // R1作为f函数的输入与8位子密钥K2参与函数运算,运算结果与L1异或,结果作为下一轮的L2
146 uint res = Merge(L2, R2, 4); //
147 res = Permutation(res, 8, IP_1); // 逆置换IP-1
148 return res;
149 }
150
151 // S-DES 解密
152 uint Decryption(uint Cip, uint K_1, uint K_2) {
153 Cip = InversePermutation(Cip, 8, IP_1);
154 PII pii = Split(Cip, 4);
155 uint L2 = pii.first;
156 uint R2 = pii.second;
157 uint R1 = R2;
158 uint L1 = L2 ^ (Function(R1, K_2));
159 uint R0 = L1;
160 uint L0 = R1 ^ (Function(R0, K_1));
161 uint res = Merge(L0, R0, 4);
162 res = InversePermutation(res, 8, IP);
163 return res;
164 }
165 public:
166 // 将数字以二进制形式输出
167 void PrintBinary(uint b) {
168 if (b == 0) {
169 printf("0\n");
170 return;
171 }
172 VI vec;
173 vec.clear();
174 while (b > 0) {
175 if (b & 1) vec.push_back(1);
176 else vec.push_back(0);
177 b >>= 1;
178 }
179 for (auto it = vec.rbegin(); it != vec.rend(); it++) {
180 printf("%d", *it);
181 }
182 printf("\n");
183 }
184
185 // 将二进制字符串转换为数字
186 uint StringToBinary(const std::string &Str) {
187 uint res = 0;
188 uint len = Str.length();
189 for (uint i = 0; i < len; i++) {
190 res <<= 1;
191 if (Str[i] == '1') res |= 1;
192 }
193 return res;
194 }
195
196 // 加密一个单位的数据
197 uint EncryptInt(uint Text, uint MasterKey) {
198 auto p = GetSubPsw(MasterKey);
199 uint K_1 = p.first;
200 uint K_2 = p.second;
201 uint res = S_DES_Main(Text, K_1, K_2);
202 return res;
203 }
204
205 // 按字符加密一个字符串
206 VI EncryptString(const String &Str, uint MasterKey) {
207 VI res;
208 auto p = GetSubPsw(MasterKey);
209 uint K_1 = p.first;
210 uint K_2 = p.second;
211 int len = Str.length();
212 for (int i = 0; i < len; i++) {
213 uint e = S_DES_Main((uint)Str[i], K_1, K_2);
214 res.push_back(e);
215 }
216 return res;
217 }
218
219 // 加密一组vector中的数字
220 VI EncryptVector(const VI &Arr, uint MasterKey) {
221 VI res;
222 auto p = GetSubPsw(MasterKey);
223 uint K_1 = p.first;
224 uint K_2 = p.second;
225 int len = Arr.size();
226 for (int i = 0; i < len; i++) {
227 uint e = S_DES_Main(Arr[i], K_1, K_2);
228 res.push_back(e);
229 }
230 return res;
231 }
232
233 // 加密长度为n的数组中的数字
234 VI EncryptArray(const uint Arr[], int n, uint MasterKey) {
235 VI res;
236 auto p = GetSubPsw(MasterKey);
237 uint K_1 = p.first;
238 uint K_2 = p.second;
239 for (int i = 0; i < n; i++) {
240 uint e = S_DES_Main(Arr[i], K_1, K_2);
241 res.push_back(e);
242 }
243 return res;
244 }
245
246 // 加密长度为n的Byte数组
247 VI EncryptBytes(const uchar Arr[], int n, uint MasterKey) {
248 VI res;
249 auto p = GetSubPsw(MasterKey);
250 uint K_1 = p.first;
251 uint K_2 = p.second;
252 for (int i = 0; i < n; i++) {
253 uint e = S_DES_Main((uint)Arr[i], K_1, K_2);
254 res.push_back(e);
255 }
256 return res;
257 }
258
259 // 加密一个文件中的数据
260 VI EncryptFile(char FileName[], uint MasterKey) {
261 VI res;
262 std::ifstream fin(FileName, std::ios::binary);
263 if (!fin.is_open()) return res;
264 int n = (int)fin.gcount();
265 char pc;
266 for (int i = 0; i < n; i++) {
267 fin.read(&pc, sizeof(uchar));
268 res.push_back((uint)pc);
269 }
270 return res;
271 }
272
273 // 解密一个单位的数据
274 uint DecryptInt(uint Cip, uint MasterKey) {
275 auto p = GetSubPsw(MasterKey);
276 uint K_1 = p.first;
277 uint K_2 = p.second;
278 uint res = Decryption(Cip, K_1, K_2);
279 return res;
280 }
281
282 // 解密vector中的数据
283 VI DecryptVector(const VI& Cips, uint MasterKey) {
284 auto p = GetSubPsw(MasterKey);
285 uint K_1 = p.first;
286 uint K_2 = p.second;
287 VI res;
288 for (auto it = Cips.begin(); it != Cips.end(); it++) {
289 uint des = Decryption(*it, K_1, K_2);
290 res.push_back(des);
291 }
292 return res;
293 }
294
295 // 将vector中的数据转化为string类型
296 String VectorToString(const VI& vec) {
297 String res;
298 for (auto it = vec.begin(); it != vec.end(); it++) {
299 res.push_back((char)*it);
300 }
301 return res;
302 }
303 };
304
305 const S_DES::VI S_DES::P_10{ 3, 5, 2, 7, 4, 10, 1, 9, 8, 6 };
306 const S_DES::VI S_DES::P_8{ 6, 3, 7, 4, 8, 5, 10, 9 };
307 const S_DES::VI S_DES::P_4{ 2, 4, 3, 1 };
308 const S_DES::VI S_DES::IP{ 2, 6, 3, 1, 4, 8, 5, 7 };
309 const S_DES::VI S_DES::IP_1{ 4, 1, 3, 5, 7, 2, 8, 6 };
310 const S_DES::VI S_DES::EP{ 4, 1, 2, 3, 2, 3, 4, 1 };
311 const S_DES::VVI S_DES::S_1{ { 1, 0, 3, 2 },
312 { 3, 2, 1, 0 },
313 { 0, 2, 1, 3 },
314 { 3, 1, 3, 2 } };
315 const S_DES::VVI S_DES::S_2{ { 0, 1, 2, 3 },
316 { 2, 0, 1, 3 },
317 { 3, 0, 1, 0 },
318 { 2, 1, 0, 3 } };