cyendra

Azarath Metrion Zinthos

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

Simplified Data Encryption Standard S-DES 是一个供教学的非安全的加密算法,它与DES的特性和结构类似,但参数小,明文分组为8位,主密钥分组为10位,采用两轮迭代。

S-DES加密过程包含两个重要部分:子密码生成过程,f函数结构。

S-DES加密原理:

S-DES的子密码生成过程:

S-DES的f函数结构:

S-DES的S盒:

通过对主加密过程进行翻转来解密。

实现代码:

  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 } };

 

posted on 2014-09-10 19:20  cyendra  阅读(1876)  评论(0编辑  收藏  举报