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 "); 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(" "); 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 } };