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接口
  • 相关阅读:
    21.错误和异常
    20.装饰器相关
    19.装饰器
    18.函数编程的练习
    Remove Duplicates from Sorted List II
    Ubuntu 12.04输入密码登陆后又跳回到登录界面
    Remove Linked List Elements
    Populating Next Right Pointers in Each Node *
    Convert Sorted Array to Binary Search Tree
    Flatten Binary Tree to Linked List *
  • 原文地址:https://www.cnblogs.com/zinthos/p/3981837.html
Copyright © 2011-2022 走看看