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 } };
时间: 2024-10-13 12:48:42