zoukankan      html  css  js  c++  java
  • DES加密系统的实现

    这是一个高内聚低耦合可复用的DES加密系统的实现。

    Github 链接:https://github.com/cyendra/CyDES

    要实现加密系统,先考虑数据的基本单位。

    在DES加密中,数据是以64位为一组的(unsigned long long),我们称它为Bit。

    加密过程中会对Bit做位移操作(左移、右移、循环左移、循环右移),也会做位运算(And、Or、Xor),还会做分割以及合并等操作。

    我们设计一个类Bit来封装这些操作,作为数据的基本单位。

      1 /*
      2     表示64位以下的数据
      3     可以做常见的位运算
      4 */
      5 class Bit {
      6 private:
      7     unsigned long long bit;// 表示数据,最多64位
      8     int size;// 表示数据的位数,不超过64位
      9 public:
     10     // 值为0的64位数据
     11     Bit();
     12 
     13     // 值为_bit的64位数据
     14     Bit(unsigned long long _bit);
     15 
     16     // 值为_bit的n位数据,当n>64位时截断
     17     Bit(unsigned long long _bit, int n);
     18 
     19     Bit(const Bit& b);
     20     Bit& operator=(Bit& b);
     21     //Bit& operator=(unsigned char num);
     22     
     23     // 由byte构造8位Bit对象
     24     void Byte(unsigned char num);
     25 
     26     // 直接左移d位
     27     void LeftShift(int d);
     28 
     29     // 循环左移d位
     30     void LeftRotate(int d);
     31 
     32     // 直接右移d位
     33     void RightShift(int d);
     34 
     35     // 循环右移d位
     36     void RightRotate(int d);
     37 
     38     // 将第pos位设置为1
     39     // pos从左向右从0开始计数,超过size位时无效
     40     void Set(int pos);
     41 
     42     // 将所有位都设置为1
     43     void Set();
     44 
     45     // 将第pos位设置为0
     46     // pos从左向右从0开始计数,超过size位时无效
     47     void Reset(int pos);
     48 
     49     // 将所有位都设置为0
     50     void Reset();
     51 
     52     // 将第pos位取反
     53     // pos从左向右从0开始计数,超过size位时无效
     54     void Flip(int pos);
     55 
     56     // 将所有位都取反
     57     void Flip();
     58 
     59     // 当所有位都为0时返回true
     60     bool None();
     61 
     62     // 当任意位为1时返回true
     63     bool Any();
     64 
     65     // 统计所有位中1的个数
     66     int Count();
     67 
     68     // 数据的有效位数
     69     int Size();
     70 
     71     // 当第pos位的值为1时返回true
     72     // pos从左向右从0开始计数,超过size位时无效
     73     bool operator[](int pos);
     74 
     75     // 将数据以unsigned long long的形式返回
     76     unsigned long long ToULL();
     77 
     78     // 将所有二进制位以二进制串形式返回
     79     std::string ToString();
     80 
     81     // 静态方法,将数据bit从中间分割为两份数据
     82     static std::pair<Bit, Bit> Split(Bit bit);
     83 
     84     // 静态方法,把数据bit平分为n份,n为偶数,bit的size能被n整除
     85     static std::vector<Bit> Split(Bit bit, int n);
     86 
     87     // 静态方法,将两份数据合并为一份数据
     88     static Bit Merge(Bit L, Bit R);
     89 
     90     // 静态方法,将Bit数组中从L到R之间的数据合并为一份数据
     91     static Bit Merge(Bit b[], int L, int R);
     92 
     93     // 静态方法,求两份数据的异或值
     94     static Bit Xor(Bit x, Bit y);
     95 
     96     // 静态方法,求两份数据的OR
     97     static Bit Or(Bit x, Bit y);
     98 
     99     // 静态方法,求两份数据的AND
    100     static Bit And(Bit x, Bit y);
    101 };
    Bit类

    DES加密过程的原理其实就是16轮迭代,而迭代过程中有两个重要的处理:子密钥生成和f函数。

    所以先不考虑主加密过程,考虑子密钥和f函数的抽象。

    虽然子密钥有16之多,但是我们只要有了主密钥就可以生成全部的16个子密钥。

    我们把这个过程抽象出来,即输入主密钥,得到一个装有16个子密钥的动态数组:

    1 /*
    2     主密钥产生子密钥的接口
    3     单例模式
    4 */
    5 class IKeyManager :public Uncopyable {
    6 public:
    7     // 通过主密钥产生子密钥
    8     virtual std::vector<Bit> GetKeys(Bit MasterKey) = 0;
    9 };
    IKeyManager接口

    接下来考虑f函数,它接受一个32位的数据和一个48位的子密钥,返回32位的加密数据。

     1 /*
     2     DES中f函数的接口
     3     单例模式
     4     其值通过32位的数据与48位的子密钥计算而来
     5 */
     6 class IFunction :public Uncopyable {
     7 public:
     8     // f函数
     9     // bit为32位的R_{i-1},Key为48位的K_i
    10     virtual Bit ProcessKey(Bit bit, Bit Key) = 0;
    11 };
    IFunction接口

    有了这两个类,主加密过程就容易实现了。

    考虑到主加密过程一次只能处理64位的数据,而实际应用中要多次调用主加密过程来加密长数据。

    因此为了避免重复计算子密钥,要在调用主加密过程之前先设置好主秘钥。

    解密操作是加密操作的逆操作,所以放在一起实现。

     1 /*
     2     Data Encryption Standard 接口
     3     继承此接口的派生类可以完成以下操作:
     4     1-接受一个主密钥
     5     2-对一组数据加密
     6     3-对一组数据解密
     7 */
     8 class IDes {
     9 public:
    10     // 将64位的key设置为主密钥
    11     virtual void SetMasterKey(Bit key) = 0;
    12     
    13     // 加密明文组dat
    14     virtual Bit Encryption(Bit dat) = 0;
    15     
    16     // 解密密文组dat
    17     virtual Bit Decryption(Bit dat) = 0;
    18 };
    IDes接口

    这样一来,DES的框架就准备好了,实现的时候有两个较复杂的逻辑:置换表操作和S-Box取值操作。

    因此单独把这两个操作抽象出来。设计一个类表示置换表,一个类管理置换表,一个类表示S-Box,一个类管理S-Box。

     1 /*
     2     置换表接口
     3 */
     4 class IPermutationTable {
     5 public:
     6     // 置换表中元素个数
     7     virtual int Size() = 0;
     8 
     9     // 获取表中第pos个元素
    10     // pos从0开始计数
    11     virtual int Get(int pos) = 0;
    12 };
    IPermutationTable接口
     1 /*
     2     DES中置换表的管理器接口
     3     单例模式
     4     它管理所有DES中要用到的置换表
     5 */
     6 class IPmtTableManager :public Uncopyable {
     7 public:
     8     // 获取初始置换表IP
     9     virtual IPermutationTable* GetIPTable() = 0;
    10 
    11     // 获取逆初始置换表IP-1
    12     virtual IPermutationTable* GetIPRevTable() = 0;
    13     
    14     // 获取扩增排列表E
    15     virtual IPermutationTable* GetETable() = 0;
    16     
    17     // 获取缩减排列表P
    18     virtual IPermutationTable* GetPTable() = 0;
    19     
    20     // 获取密钥排列PC-1
    21     virtual IPermutationTable* GetPC1Table() = 0;
    22     
    23     // 获取密钥排列PC-2
    24     virtual IPermutationTable* GetPC2Table() = 0;
    25 };
    IPmtTableManager接口
    1 // S-Box的接口
    2 class ISBox {
    3 public:
    4     // 通过6位数据pos获取S-Box中的值
    5     virtual Bit Get(Bit pos) = 0;
    6 
    7     // 通过指定的坐标(i,j)获取S-Box中的值
    8     virtual Bit Get(int i, int j) = 0;
    9 };
    ISBox接口
     1 /*
     2     S-Box管理器的接口
     3     单例模式
     4     它能够返回指定编号的S-Box
     5 */
     6 class ISBoxManager :public Uncopyable {
     7 public:
     8     // 返回指向编号为i的S-Box的指针
     9     virtual SBox* GetSBox(int i) = 0;
    10 };
    ISBoxManager接口

    只有置换表还不够,置换操作也是一个较复杂的操作,应该单独抽象出来处理。

     1 /*
     2     置换操作的接口
     3     单例模式
     4 */
     5 class IPermutationManager :public Uncopyable {
     6 public:
     7     // 用置换表table对数据bit进行置换
     8     virtual Bit Permutation(Bit bit, IPermutationTable* table) = 0;
     9     // 用置换表table对数据bit进行逆置换
    10     virtual Bit InversePermutation(Bit bit, IPermutationTable* table) = 0;
    11 };
    IPermutationManager接口

    如此一来,在添加具体实现细节以后,DES主加密过程就能顺利实现了。

    为了加密长数据,我们为之前的代码套上一层外壳。

    用一个类来与用户进行交互,使它可以以用户指定的分组方式来对数据分组并调用主加密过程。

    /*
        加密器接口
    */
    class IEncryptor {
    public:
        // 分组操作方案
        enum Type {
            ECB, CBC, CFB, OFB
        };
    
        // 加密字符串 
        virtual std::vector<unsigned char> EncryptString(const std::string& string, Bit MasterKey, Type type) = 0;
        
        // 解密字符串
        virtual std::string DecryptString(const std::vector<unsigned char>& bins, Bit MasterKey, Type type) = 0;
        
        // 加密二进制串
        virtual std::vector<unsigned char> EncryptBinary(const std::vector<unsigned char>& bins, Bit MasterKey, Type type) = 0;
        
        // 解密二进制串
        virtual std::vector<unsigned char> DecryptBinary(const std::vector<unsigned char>& bins, Bit MasterKey, Type type) = 0;
        
        // 加密文件
        virtual std::vector<unsigned char> EncryptFile(char *filename, Bit MasterKey, Type type) = 0;
        
        // 解密文件
        virtual std::vector<unsigned char> DecryptFile(char *filename, Bit MasterKey, Type type) = 0;
        
        // 保存二进制串到文件
        virtual void SaveBinaryAsFile(const std::vector<unsigned char>& bins, char *filename) = 0;
    };
    IEncryptor接口

    最后将具体的分组过程实现即可。

    1 /*
    2     区块加密法的操作模式接口
    3 */
    4 class IMode :public Uncopyable {
    5 public:
    6     virtual std::vector<unsigned char> EncryptBinary(IDes* des, const std::vector<unsigned char>& bins, Bit MasterKey) = 0;
    7     virtual std::vector<unsigned char> DecryptBinary(IDes* des, const std::vector<unsigned char>& bins, Bit MasterKey) = 0;
    8 };
    IMode接口
  • 相关阅读:
    函数式宏定义与普通函数
    linux之sort用法
    HDU 4390 Number Sequence 容斥原理
    HDU 4407 Sum 容斥原理
    HDU 4059 The Boss on Mars 容斥原理
    UVA12653 Buses
    UVA 12651 Triangles
    UVA 10892
    HDU 4292 Food
    HDU 4288 Coder
  • 原文地址:https://www.cnblogs.com/zinthos/p/3981837.html
Copyright © 2011-2022 走看看