码迷,mamicode.com
首页 > 其他好文 > 详细

S-DES加密

时间:2014-09-10 20:51:51      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   color   io   os   ar   for   文件   

 

 

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

 

S-DES加密

标签:des   style   blog   color   io   os   ar   for   文件   

原文地址:http://www.cnblogs.com/zinthos/p/3965024.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!