• S-DES加密


    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 } };
  • 相关阅读:
    C#.NET Split 的几种使用方法
    给网站指明手机网网站
    手机访问网站自动跳转到手机版
    手机网页点击链接触发手机自动拨打或保存电话的代码
    图片切换效果2(定时+左右按钮)
    java HttpClient设置代理
    将应用部署到Tomcat根目录的方法
    Java中ArrayList类的用法
    JSP/Serlet 使用fileupload上传文件
    java 格式化字符串
  • 原文地址:https://www.cnblogs.com/zinthos/p/3965024.html
Copyright © 2020-2023  润新知