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接口

 

你可能感兴趣的:(des)