首页 > 代码库 > S-DES加密

S-DES加密

 

 

  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置换,得到K2103         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位异或秘钥K110         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位L0127         uint R0 = pii.second;                      // 右4位R0128         uint L1 = R0;                              // 第一轮运算,R0作为下一轮的L1129         uint R1 = L0 ^ (Function(R0, K_1));          // R0作为f函数的输入与8位子秘钥K1参与函数运算,运算结构与L0异或,结果作为下一轮的R1130         uint R2 = R1;                              // 第二轮运算,R1作为下一轮的R2131         uint L2 = L1 ^ (Function(R1, K_2));       // R1作为f函数的输入与8位子密钥K2参与函数运算,运算结果与L1异或,结果作为下一轮的L2132         uint res = Merge(L2, R2, 4);              // 133         res = Permutation(res, 8, IP_1);          // 逆置换IP-1134         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加密