狂自私

导航

DES和3DES算法实现

是模仿的写的。

C语言原版的:

#include <stdio.h>
#include <memory.h>
#include <string.h>


typedef bool(*PSubKey)[16][48];
enum { ENCRYPT, DECRYPT };             //选择:加密;解密
static bool SubKey[2][16][48];         // 16圈子密钥
static bool Is3DES;                    // 3次DES标志
static char Tmp[256], deskey[16];      //暂存字符串,密钥串


static void DES(char Out[8], char In[8], const PSubKey pSubKey, bool Type);//标准DES加/解密
static void SetKey(const char* Key, int len);// 设置密钥
static void SetSubKey(PSubKey pSubKey, const char Key[8]);// 设置子密钥
static void F_func(bool In[32], const bool Ki[48]);// f 函数
static void S_func(bool Out[32], const bool In[48]);// S 盒代替
static void Transform(bool* Out, bool* In, const char* Table, int len);// 变换
static void Xor(bool* InA, const bool* InB, int len);// 异或
static void RotateL(bool* In, int len, int loop);// 循环左移
static void ByteToBit(bool* Out, const char* In, int bits);// 字节组转换成位组
static void BitToByte(char* Out, const bool* In, int bits);// 位组转换成字节组


// Type(选择)—ENCRYPT:加密,DECRYPT:解密
// 输出缓冲区(Out)的长度 >= ((datalen+7)/8)*8,即比datalen大的且是8的倍数的最小正整数
// In 可以= Out,此时加/解密后将覆盖输入缓冲区(In)的内容
// 当keylen>8时系统自动使用3次DES加/解密,否则使用标准DES加/解密.超过16字节后只取前16字节


//加密解密函数:
bool DES_Act(char* Out, char* In, long datalen, const char* Key, int keylen, bool Type = ENCRYPT);





//int main()
//{
//    char plain_text[100] = { "2022年9月3日14:58:48" };                         // 设置明文
//
//    char key[100] = { "C/C++" };                               // 密钥设置
//
//
//    /*printf("请输入明文:\n");
//    gets_s(plain_text);
//
//
//
//    printf("\n 请输入密钥:\n");
//    gets_s(key);*/
//
//
//    char encrypt_text[255];                       // 密文
//    char decrypt_text[255];                       // 解密文
//
//    memset(encrypt_text, 0, sizeof(encrypt_text));//memset(a,b,c)函数,在a的地址开始到c的长度的字节都初始化为b
//    memset(decrypt_text, 0, sizeof(decrypt_text));
//
//
//
//    // 进行DES加密:
//    //DES_Act(encrypt_text, plain_text, sizeof(plain_text), key, sizeof(key), ENCRYPT);
//    DES_Act(encrypt_text, plain_text, strlen(plain_text), key, strlen(key), ENCRYPT);
//
//
//    printf("\nDES加密后的密文:\n");
//    printf("%s\n\n", encrypt_text);
//
//
//    // 进行DES解密:
//    //DES_Act(decrypt_text, encrypt_text, sizeof(plain_text), key, sizeof(key), DECRYPT);
//    DES_Act(decrypt_text, encrypt_text, strlen(plain_text), key, strlen(key), DECRYPT);
//    printf("\n解密后的输出:\n");
//    printf("%s", decrypt_text);
//
//
//    printf("\n\n");
//    getchar();
//    return 0;
//}


//下面是DES算法中用到的各种表:

// 初始置换IP表
const static char IP_Table[64] =
{
    58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
    62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
    57, 49, 41, 33, 25, 17,  9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
    61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
};


// 逆初始置换IP1表
const static char IP1_Table[64] =
{
    40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
    38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
    36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
    34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41,  9, 49, 17, 57, 25
};


// 扩展置换E表
static const char Extension_Table[48] =
{
    32,  1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,
     8,  9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
    16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
    24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32,  1
};


// P盒置换表
const static char P_Table[32] =
{
    16, 7, 20, 21, 29, 12, 28, 17, 1,  15, 23, 26, 5,  18, 31, 10,
    2,  8, 24, 14, 32, 27, 3,  9,  19, 13, 30, 6,  22, 11, 4,  25
};


// 密钥置换表
const static char PC1_Table[56] =
{
    57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
    10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
    63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
    14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
};


// 压缩置换表
const static char PC2_Table[48] =
{
    14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
    23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
    41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
    44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
};


// 每轮移动的位数
const static char LOOP_Table[16] =
{
    1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};


// S盒设计
const static char S_Box[8][4][16] =
{
    // S盒1
    14,     4,    13,     1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
     0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
     4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
    15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
    // S盒2
    15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
     3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
     0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
    13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
    // S盒3
    10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
    13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
    13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
     1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
     // S盒4
      7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
     13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
     10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
      3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
      // S盒5
       2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
      14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
       4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
      11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
      // S盒6
      12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
      10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
       9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
       4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
       // S盒7
        4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
       13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
        1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
        6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
        // S盒8
        13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
         1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
         7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
         2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
};



//下面是DES算法中调用的函数:

// 字节转换函数
void ByteToBit(bool* Out, const char* In, int bits)
{
    //if (4 == bits) {
    //    printf("ByteToBit_Out_old:");
    //    for (int i{}; i < bits; i++) {
    //        printf("%d", Out[i]);
    //    }
    //    printf("\n");
    //}
    for (int i = 0; i < bits; ++i) {
        Out[i] = (In[i >> 3] >> (i & 7)) & 1;
    }
    //In[i/8] 这个作用是取出1个字节:i=0~7的时候就取In[0], i=8~15的时候就取In[1],……
    //In[i/8] >> (i%8),是把取出来的1个字节右移0~7位,也就是依次取出那个字节的每一个bit
    //整个函数的作用是:把In里面的每个字节依次转换为8个bit,最后的结果存到Out里面
    //if (4 == bits) {
    //    printf("ByteToBit_Out_new:");
    //    for (int i{}; i < bits; i++) {
    //        printf("%d", Out[i]);
    //    }
    //    printf("\n");
    //}
    return;
}


// 比特转换函数
void BitToByte(char* Out, const bool* In, int bits)
{
    memset(Out, 0, bits >> 3);//把每个字节都初始化为0
    for (int i = 0; i < bits; ++i)
        Out[i >> 3] |= In[i] << (i & 7);//i>>3位运算,按位右移三位等于i除以8,i&7按位与运算等于i求余8;
}


// 变换函数
void Transform(bool* Out, bool* In, const char* Table, int len)
{
    for (int i = 0; i < len; ++i)
        Tmp[i] = In[Table[i] - 1];
    memcpy(Out, Tmp, len);
    //if (len == 48) {
    //    for (int i{}; i < len; i++) {
    //        printf("%d", (int)Out[i]);
    //    }
    //    printf("\n");
    //}
}


// 异或函数的实现
void Xor(bool* InA, const bool* InB, int len)
{
    printf("异或:");
    for (int i = 0; i < len; ++i) {
        printf("%d", InB[i]);
        InA[i] ^= InB[i];//异或运算,相同为0,不同为1
    }
    printf("\n");
}


// 轮转函数
void RotateL(bool* In, int len, int loop)
{
    memcpy(Tmp, In, loop);//Tmp接受左移除的loop个字节
    memcpy(In, In + loop, len - loop);//In更新即剩下的字节向前移动loop个字节
    memcpy(In + len - loop, Tmp, loop);//左移除的字节添加到In的len-loop的位置
}


// S函数的实现
void S_func(bool Out[32], const bool In[48])  //将8组,每组6 bits的串,转化为8组,每组4 bits
{
    bool* t_out = Out;
    char t;
    printf("S盒:");
    for (char i = 0, j, k; i < 8; ++i, In += 6, Out += 4)
    {
        j = (In[0] << 1) + In[5];//取第一位和第六位组成的二进制数为S盒的纵坐标
        k = (In[1] << 3) + (In[2] << 2) + (In[3] << 1) + In[4];//取第二、三、四、五位组成的二进制数为S盒的横坐标
        t = S_Box[i][j][k];
        printf("%d,", t);
        ByteToBit(Out, &t, 4);
    }
    printf("\nOut:");
    for (int i{}; i < 32; i++) {
        printf("%d", t_out[i]);
    }
    printf("\n");
}


// F函数的实现
void F_func(bool In[32], const bool Ki[48])
{
    static bool MR[48];
    Transform(MR, In, Extension_Table, 48);   //先进行 E 扩展

    Xor(MR, Ki, 48);                          //再异或

    S_func(In, MR);                           //各组字符串分别经过各自的 S 盒
    //debug
    printf("In:");
    for (int i{}; i < 32; i++) {
        printf("%d", In[i]);
    }
    printf("\n");
    /////////
    Transform(In, In, P_Table, 32);           //最后 P 变换
}



// 设置子密钥
void SetSubKey(PSubKey pSubKey, const char Key[8])
{
    static bool K[64], * KL = &K[0], * KR = &K[28]; //将64位密钥串去掉8位奇偶位后,分成两份
    ByteToBit(K, Key, 64);                    //转换格式
    Transform(K, K, PC1_Table, 56);

    for (int i = 0; i < 16; ++i)                   // 由56位密钥产生48位子密钥
    {
        RotateL(KL, 28, LOOP_Table[i]);       //两份子密钥分别进行左移转换
        RotateL(KR, 28, LOOP_Table[i]);
        Transform((*pSubKey)[i], K, PC2_Table, 48);
    }
}


// 设置密钥
void SetKey(const char* Key, int len)
{
    memset(deskey, 0, 16);
    memcpy(deskey, Key, len > 16 ? 16 : len);//memcpy(a,b,c)函数,将从b地址开始到c长度的字节的内容复制到a
    SetSubKey(&SubKey[0], &deskey[0]);// 设置子密钥
    Is3DES = len > 8 ? (SetSubKey(&SubKey[1], &deskey[8]), true) : false;
}


// DES加解密函数
void DES(char Out[8], char In[8], const PSubKey pSubKey, bool Type)
{
    static bool M[64], tmp[32], * Li = &M[0], * Ri = &M[32];  //64 bits明文 经过IP置换后,分成左右两份
    ByteToBit(M, In, 64);
    Transform(M, M, IP_Table, 64);
    //debug
    printf("M:");
    for (int i{}; i < 64; i++) {
        printf("%d", M[i]);
    }
    printf("\n");
    /////////
    if (Type == ENCRYPT)                               //加密
    {
        for (int i = 0; i < 16; ++i)                         //加密时:子密钥 K0~K15
        {
            //debug
            printf("M:");
            for (int i{}; i < 64; i++) {
                printf("%d", M[i]);
            }
            printf("\n");
            /////////

            memcpy(tmp, Ri, 32);
            F_func(Ri, (*pSubKey)[i]);                  // 调用F函数

            printf("Ri:");
            for (int i{}; i < 32; i++) {
                printf("%d", Ri[i]);
            }
            printf("\n");

            Xor(Ri, Li, 32);                            //Li与Ri异或

            printf("Li:");
            for (int i{}; i < 32; i++) {
                printf("%d", Li[i]);
            }
            printf("\n");
            printf("Ri:");
            for (int i{}; i < 32; i++) {
                printf("%d", Ri[i]);
            }
            printf("\n");

            memcpy(Li, tmp, 32);

            printf("Li:");
            for (int i{}; i < 32; i++) {
                printf("%d", Li[i]);
            }
            printf("\n");

        }
    }
    else                 //解密
    {
        for (int i = 15; i >= 0; --i)                        // 解密时:Ki的顺序与加密相反
        {
            memcpy(tmp, Li, 32);
            F_func(Li, (*pSubKey)[i]);
            Xor(Li, Ri, 32);
            memcpy(Ri, tmp, 32);
        }
    }
    Transform(M, M, IP1_Table, 64);                     //最后经过逆初始置换IP-1,得到密文/明文
    BitToByte(Out, M, 64);
    for (int i{}; i < 8; i++) {
        printf("%d,", Out[i]);
    }
    printf("\n");
}


// DES加解密函数(可以对长明文分段加密)
bool DES_Act(char* Out, char* In, long datalen, const char* Key, int keylen, bool Type)
{
    //(datalen = (datalen + 7) & 0xfffffff8):这里在对齐计算为8的倍数
    if (!(Out && In && Key && (datalen = (datalen + 7) & 0xfffffff8)))
        return false;
    SetKey(Key, keylen);
    if (!Is3DES)
    {                                                   // 1次DES
        for (long i = 0, j = datalen >> 3; i < j; ++i, Out += 8, In += 8)
            DES(Out, In, &SubKey[0], Type);
    }
    else
    {                // 3次DES 加密:加(key0)-解(key1)-加(key0) 解密::解(key0)-加(key1)-解(key0)
        for (long i = 0, j = datalen >> 3; i < j; ++i, Out += 8, In += 8) {
            DES(Out, In, &SubKey[0], Type);
            DES(Out, Out, &SubKey[1], !Type);
            DES(Out, Out, &SubKey[0], Type);
        }
    }
    return true;
}
View Code

C++仿制版本的:

DES_3.h

#pragma once
#include <string>
#include <array>
#include <bitset>
#include <iostream>
#include <vector>


class DES_3
{
public:
    DES_3();
public:
    /*
    * 获取加解密后的结果,返回char*字符串
    */
    const char* get_result_text()const { return this->result_text.c_str(); }
    /*
    * 加密、解密的枚举
    */
    enum En_De_cryption_enum
    {
        ENCRYPT, DECRYPT
    }; 
    /*
    * 设置密钥,key必须大于等于8
    */
    void setKey(std::string key);
    /*
    * 设置明文
    */
    void set_plain_text(std::string& plain_text) { this->plain_text = plain_text; }
    /*
    * 加解密函数
    */
    bool DES_Act(En_De_cryption_enum Type);

protected:
    /*
    * 将char字符转换为二进制
    * Out:结果保存的地方,需要确保该参数长度足够且存放的位置正确
    * In:待转化的字符串
    * bits_len:字符数*8
    */
    void ByteToBit(std::vector<bool>& Out, std::string& In, size_t bits_len);
    /*
    * 将二进制转化为char字符
    * Out:保存结果的地方;
    * In:待转化的二进制
    * bits_len:In的长度
    */
    void BitToByte(std::string& Out, std::vector<bool>& In, size_t bits_len);
    /*
    * 通过各种Table表,将In转化为Out,比如通过表将64位的In输出为56位的Out
    */
    void Transform(std::vector<bool>& Out, std::vector<bool>& In, std::vector< unsigned short> Table, size_t Len);
    /*
    * 异或,InA和InB异或,将结果输出到InA
    */
    void Xor(std::vector<bool>& InA, std::vector<bool>& InB, size_t Len);
    /*
    * 将32位的Out经过In拓展到48位;
    */
    void S_func(std::vector<bool>& Out, std::vector<bool>& In);
    /*
    * 循环左移
    */
    void RotateL(std::vector<bool>& In, size_t Len, size_t Loop);
    /*
    * 把32位的In拓展到48位,然后异或计算,通过S盒,在通过最终的变换定义表。
    */
    void F_func(std::vector<bool>& In, std::vector<bool>& Ki);
    /*
    * 设置子密钥
    */
    void SetSubKey(std::vector<std::vector<bool>> &pSub_Key, std::string & key);
    /*调用SetSubKey*/
    void call_SetSubKey();
    /*
    * 一次性只加解密8个char字符
    */
    void DES(std::string &Out, std::string& In, std::vector<std::vector<bool>> &pSubKey, En_De_cryption_enum Type);
private:

    //明文
    std::string plain_text;
    //密钥
    std::string Key;
    //密文
    std::string cipher_text;
    //加密或者解密后的结果
    std::string result_text;
    //
    std::vector<bool> s_k;
    //
    std::vector<std::vector<bool>> pSubKey;
    //子密钥
    std::vector<std::vector<std::vector<bool>>> subKey;
    //3次DES标志
    bool Is3DES{};
    //暂存字符串
    std::string Tmp;
    //初始置换IP表
    std::vector< unsigned short> IP_Table={
        58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,
        62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,
        57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,
        61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7
    };
    //逆初始置换IP表
    std::vector< unsigned short>IP1_Table ={
        40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31,
        38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29,
        36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27,
        34,2,42,10,50,18,58,26,33,1,41,9,49,17,57,25
    };
    //拓展置换E表
    std::vector < unsigned short> Extension_Table {
        32,1,2,3,4,5,4,5,6,7,8,9,
        8,9,10,11,12,13,12,13,14,15,16,17,
        16,17,18,19,20,21,20,21,22,23,24,25,
        24,25,26,27,28,29,28,29,30,31,32,1
    };
    //P盒置换表
    std::vector < unsigned short>P_Table {
        16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10,
        2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25
    };
    //密钥置换表
    std::vector < unsigned short>PC1_Table {
        57,49,41,33,25,17,9,1,58,50,42,34,26,18,
        10,2,59,51,43,35,27,19,11,3,60,52,44,36,
        63,55,47,39,31,23,15,7,62,54,46,38,30,22,
        14,6,61,53,45,37,29,21,13,5,28,20,12,4
    };
    //压缩置换表
    std::vector < unsigned short>PC2_Table {
        14,17,11,24,1,5,3,28,15,6,21,10,
        23,19,12,4,26,8,16,7,27,20,13,2,
        41,52,31,37,47,55,30,40,51,45,33,48,
        44,49,39,56,34,53,46,42,50,36,29,32
    };
    //每轮移动的位数
    std::vector < unsigned short>LOOP_Table{
        {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 }
    };
    /*
    S盒设计
    这里的语法有点令人摸不着头脑,简单来说std::array是一个没有构造函数的聚合,可以理解为struct,
    std::array是有一个原生数组的。
    可以参考:https://zhuanlan.zhihu.com/p/353368820
    */
    std::vector<std::vector < std::vector<unsigned short>>> S_Box{  //std::array的初始化
        {    //给原生数组的初始化,8个元素
            //S盒1
            {    //给第二层std::array的初始化
                {    // 给第二层std::array的原生数组的初始化
                    {    //给第三层std::array的初始化
                        {14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7}    //// 给第三层std::array的原生数组的初始化
                    },
                    {
                        {0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8}
                    },
                    {
                        {4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0}
                    },
                    {
                        {15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13}
                    },
                }
            },
        //S盒2
            {
                {
                    {15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10},
                    {3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5},
                    {0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15},
                    {13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9},
                }
            },
        //S盒3
            {
                {
                    {10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8},
                    {13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1},
                    {13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7},
                    {1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12},
                }    
            },
        //S盒4
            {
                {
                    {7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15},
                    {13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9},
                    {10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4},
                    {3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14},
                }
            },
        //S盒5
            {
                {
                    {2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9},
                    {14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6},
                    {4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14},
                    {11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3},
            
                }
            },
        //S盒6
            {    
                {
                    {12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11},
                    {10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8},
                    {9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6},
                    {4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13},
                }
            },
        //S盒7
            {
                {
                    {4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1},
                    {13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6},
                    {1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2},
                    {6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12},
                }
            },
        //S盒8
            {
                {
                    {13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7},
                    {1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2},
                    {7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8},
                    {2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11},
                }
            },
        }
    };

};
View Code

DES_3.cpp

#include "DES_3.h"
DES_3::DES_3() {
    this->s_k.resize(48, 0);
    this->pSubKey.resize(16, this->s_k);
    this->subKey.resize(2, this->pSubKey);
}
void DES_3::ByteToBit(std::vector<bool>& Out, std::string& In, size_t bits_len) {
    //设置Out的长度
    //Out.resize(bits_len, 0);
    //if (4 == bits_len) {
    //    std::cout << "ByteToBit_Out_old:";
    //    for (int i{}; i < bits_len; i++) {
    //        std::cout << Out[i];
    //    }
    //    std::cout << std::endl;
    //}
    for (size_t i{}; i < bits_len; i++) {
        /*
        * int是4字节32位,char是1字节8位
        *
        * C/C++的位移是逻辑不循环位移,就是说超出位置的数字会消失掉
        * 位移是整体移动,而非某个位移动
        * 8的二进制为1000,右移3位为1,即i=0~7的时候In[i >> 3]都取出的是In[0];8~15的时候取出的是In[1];
        * 同理,随着i增加,每跨越8个数字,i>>3的结果就增加1
        *
        * &:按位与:同位1的位才为1,不足的部分补充0
        * 7的二进制:0111
        * 也就是说i为0~7的时候,i & 7的值为0~7;i为8~15的时候,i & 7的值也是0~7;
        * 所以,不管i的值是多少,最后i & 7的取值范围都在0~7之间
        * 所以,当i=0~7的时候,(In[i >> 3] >> (i & 7)) & 1 就是把char的每一位取出来存储到Out[i]中
        *
        */
        //int a = i >> 3;
        //int b = In[a] >> (i & 7);
        //int c = (In[(i >> 3)] >> (i & 7)) & 1;
        Out[i] = (In[(i >> 3)] >> (i & 7)) & 1;
        //Out[i] = (In[i >> 3] >> (i & 7)) & 1;
    }
    //if (4 == bits_len) {
    //    std::cout << "ByteToBit_Out_new:";
    //    for (int i{}; i < bits_len; i++) {
    //        std::cout << Out[i];
    //    }
    //    std::cout << std::endl;
    //}
    return;
}
void DES_3::BitToByte(std::string& Out, std::vector<bool>& In, size_t bits_len) {
    //设置In的长度
    //In.resize(bits_len % 8 == 0 ? bits_len : bits_len / 8 + 1, 0);
    std::string temp;
    temp.resize((bits_len >> 3), 0);
    for (size_t i{}; i < bits_len; i++) {
        /*
        * |:参加运算的两个对象只要有一个为1,其值为1
        * 这里就是把8个位组合成一个字节。就形成了一个char字符
        */
        temp[i >> 3] |= In[i] << (i & 7);
    }
    Out.swap(temp);
}
void DES_3::Transform(std::vector<bool>& Out, std::vector<bool>& In, std::vector< unsigned short> Table, size_t Len){

    std::vector<bool> temp;
    temp.resize(Len, 0);
    for (size_t i{}; i < Len; i++) {
        /*if (48 == Len) {
            int t = Table[i] - 1;
            std::cout << t << ",";
        }*/

        temp[i] = In[Table[i] - 1];        //不会发生负数的情况
    }
    /*if (48 == Len) {
        std::cout << std::endl;
    }*/
    Out = temp;
    /*if (Len == 48) {
        for (int i{}; i < Len; i++) {
            std::cout << static_cast<int>(Out[i]);
        }
        std::cout << std::endl;
    }
    return;*/
}
void DES_3::Xor(std::vector<bool>& InA, std::vector<bool>& InB, size_t Len) {
    //std::cout << "异或:";
    for (size_t i{}; i < Len; i++) {
        //std::cout << static_cast<int>(InB[i]);
        InA[i] = InA[i] ^ InB[i];
    }
    //std::cout << std::endl;
}
void DES_3::S_func(std::vector<bool>& Out, std::vector<bool>& In) {
    unsigned i, j, k;
    i = j = k = 0;
    std::string t;
    //std::cout << "S盒:";
    std::vector<bool> temp;
    temp.resize(4, 0);
    for (; i < 8; i++) {
        /*
        * 取第一位和第六位组成的二进制数为S盒 的纵坐标
        * 这里注意运算符优先级的问题
        */
        j = (In[i * 6] << 1) + (In[(i + 1) * 6 - 1]);
        /*
        * 取第二、三、四、五位组成的二进制数为S盒 的横坐标
        */
        k = (In[i * 6 + 1] << 3) + (In[i * 6 + 2] << 2) + (In[i * 6 + 3] << 1) + In[i * 6 + 4];
        /*
        * S盒对应的值转为二进制
        */
        t = static_cast<char>(this->S_Box[i][j][k]);
        //std::cout << static_cast<int>(this->S_Box[i][j][k]) << ",";
        this->ByteToBit(temp, t, 4);
        Out[i * 4] = temp[0];
        Out[i * 4 + 1] = temp[1];
        Out[i * 4 + 2] = temp[2];
        Out[i * 4 + 3] = temp[3];
    }
    /*std::cout << std::endl;
    std::cout << "Out:";
    for (int i{}; i < 32; i++) {
        std::cout << static_cast<int>(Out[i]);
    }
    std::cout << std::endl;*/
}
void DES_3::RotateL(std::vector<bool>& In, size_t Len, size_t Loop) {
    /*std::cout << "循环左移前:";
    for (unsigned i{}; i < Len; i++) {
        std::cout << static_cast<int>(In[i]);
    }
    std::cout << '\n';*/
    //循环左移
    //把前面的值插入到尾巴去
    In.insert(In.end(), In.begin(), In.begin() + Loop);
    //删除前面被移动的部分
    In.erase(In.begin(), In.begin() + Loop);
    /*std::cout << "循环左移后:";
    for (unsigned i{}; i < Len; i++) {
        std::cout << static_cast<int>(In[i]);
    }
    std::cout << '\n';*/
}
void DES_3::F_func(std::vector<bool>& In, std::vector<bool>& Ki) {
    std::vector<bool> MR;
    MR.resize(48, 0);    //设置长度为48
    //进行E拓展,将32位的In变为48位给到MR
    this->Transform(MR, In, this->Extension_Table, 48);
    
    //再异或,结果输出到MR
    this->Xor(MR, Ki, 48);
    
    ////////////
    //再经过S盒,结果输出到In
    this->S_func(In, MR);
    //debug
    /*std::cout << "In:";
    for (int i{}; i < 32; i++) {
        std::cout << static_cast<int>(In[i]);
    }
    std::cout << std::endl;*/
    //最后经过P变换,结果输出到In
    this->Transform(In, In, this->P_Table, 32);
}
void DES_3::SetSubKey(std::vector<std::vector<bool>> &pSub_Key, std::string& key) {
    /*
    * Key的长度最多也就是8个char字符
    */
    std::vector<bool> K, KL, KR;//将64位密钥串去掉8位奇偶位后,分成两份
    K.resize(64, 0);

    this->ByteToBit(K, key, 64);    //将key转化为64位二进制
    this->Transform(K, K, this->PC1_Table, 56);
    //重新设置K的长度
    //K.resize(56);
    KL.insert(KL.begin(), K.begin(), K.begin() + 28);
    KR.insert(KR.begin(), K.begin() + 28, K.end());

    //由56位秘钥产生48位子密钥
    for (int i{}; i < 16U; i++) {
        //两份子密钥分别进行左移转换
        this->RotateL(KL, 28, this->LOOP_Table[i]);
        this->RotateL(KR, 28, this->LOOP_Table[i]);
        K.clear();
        K.insert(K.begin(), KL.begin(), KL.end());
        K.insert(K.end(), KR.begin(), KR.end());
        this->Transform(pSub_Key[i], K, this->PC2_Table, 48);
    }
}
void DES_3::call_SetSubKey() {
    this->SetSubKey(this->subKey[0], this->Key);        //取的前面8个字符(64位)
        //std::cout << "subKey[0]" << std::endl;
        //for (int i{}; i < 16; i++) {
        //    std::cout << "subKey[0][" << i << "]:";
        //    for (int j{}; j < 48; j++) {
        //        std::cout << this->subKey[0][i][j];
        //    }
        //    std::cout << "\n";
        //}
    std::string Key_back_8(this->Key.begin() + 8, this->Key.end());
    this->SetSubKey(this->subKey[1], Key_back_8);        //要取后面的8个字符(64位)
        //std::cout << "subKey[1]" << std::endl;
        //for (int i{}; i < 16; i++) {
        //    std::cout << "subKey[1][" << i << "]:";
        //    for (int j{}; j < 48; j++) {
        //        std::cout << this->subKey[1][i][j];
        //    }
        //    std::cout << "\n";
        //}
    this->Is3DES = std::strlen(this->Key.c_str()) > 8 ? true : false;
}
void DES_3::setKey(std::string key) {
    this->Key = key.size() > 16 ? key.substr(0, 16) : key;
    while (this->Key.size()<16)
    {
        this->Key.push_back(0);
    }
}
void DES_3::DES(std::string &Out, std::string& In, std::vector<std::vector<bool>> &pSubKey, En_De_cryption_enum Type) {
    std::vector<bool> M, temp, Li, Ri;
    M.resize(64, 0);
    temp.resize(32, 0);

    this->ByteToBit(M, In, 64);
    ////debug
    /*std::cout << "M:";
    for (int i{}; i < 64; i++) {
        std::cout << M[i];
    }
    std::cout << std::endl;*/
    this->Transform(M, M, this->IP_Table, 64);
    //debug
    /*std::cout << "M:";
    for (int i{}; i < 64; i++) {
        std::cout << M[i];
    }
    std::cout << std::endl;*/

    if (Type == ENCRYPT) {
        //加密
        for (int i{}; i < 16; i++) {
            Li.clear();
            Ri.clear();
            Ri.insert(Ri.begin(), M.begin() + 32, M.end());
            Li.insert(Li.begin(), M.begin(), M.begin() + 32);
            
            //////debug
            /*std::cout << "M:";
            for (unsigned i{}; i < 64; i++) {
                std::cout << static_cast<int>(M[i]);
            }
            std::cout << std::endl;*/
            ///////

            this->F_func(Ri, pSubKey[i]);

            /*std::cout << "Ri:";
            for (int i{}; i < 32; i++) {
                std::cout << Ri[i];
            }
            std::cout << std::endl;*/

            this->Xor(Ri, Li, 32);

            /*std::cout << "Li:";
            for (int i{}; i < 32; i++) {
                std::cout << Li[i];
            }
            std::cout << std::endl;
            std::cout << "Ri:";
            for (int i{}; i < 32; i++) {
                std::cout << Ri[i];
            }
            std::cout << std::endl;*/
            //////////////////然后把Li和Ri替换M
            //////////////////把原本的Ri给到Li
            Li.clear();
            Li.insert(Li.end(), M.begin() + 32, M.end());
            /*std::cout << "Li:";
            for (int i{}; i < 32; i++) {
                std::cout << Li[i];
            }
            std::cout << std::endl;*/
            //把现在的Li和Ri组合成新的M
            M.clear();
            M.insert(M.end(), Li.begin(), Li.end());
            M.insert(M.end(), Ri.begin(), Ri.end());
        }
    }
    else {
        //解密
        for (int i = 15; i >= 0; i--) {//解密时,Ki的顺序与加密相反
            Li.clear();
            Ri.clear();
            Ri.insert(Ri.end(), M.begin() + 32, M.end());
            Li.insert(Li.end(), M.begin(), M.begin() + 32);
            /*std::cout << "Li:";
            for (int i{}; i < 32; i++) {
                std::cout << Li[i];
            }
            std::cout << std::endl;
            std::cout << "pSubKey[" << i << "]:";
            for (int ii{}; ii < 48; ii++) {
                std::cout << pSubKey[i][ii];
            }
            std::cout << std::endl;*/
            this->F_func(Li, pSubKey[i]);
            /*std::cout << "Li:";
            for (int i{}; i < 32; i++) {
                std::cout << Li[i];
            }
            std::cout << std::endl;*/
            this->Xor(Li, Ri, 32);
            /*std::cout << "Li:";
            for (int i{}; i < 32; i++) {
                std::cout << Li[i];
            }
            std::cout << std::endl;*/
            //然后把Li和Ri替换M
            //把原本的Li给到Ri
            Ri.clear();
            Ri.insert(Ri.end(), M.begin(), M.begin() + 32);

            //std::cout << "Ri:";
            //for (int i{}; i < 32; i++) {
            //    std::cout << Ri[i];
            //}
            //std::cout << std::endl;

            //把现在的Li和Ri组合成新的M
            M.clear();
            M.insert(M.end(), Li.begin(), Li.end());
            M.insert(M.end(), Ri.begin(), Ri.end());
        }
    }
    this->Transform(M, M, this->IP1_Table, 64);//最后经过逆初始置换IP-1,得到密文/明文
    /*std::cout << "M:";
    for (int i{}; i < 64; i++) {
        std::cout << M[i];
    }
    std::cout << std::endl;*/
    this->BitToByte(Out, M, 64);
    /*for (int i{}; i < 8; i++) {
        std::cout << static_cast<int>(Out[i]) << ",";
    }
    std::cout << std::endl;*/
}
bool DES_3::DES_Act(En_De_cryption_enum Type) {
    if (this->plain_text.size() > 0 && this->Key.size() > 0) {
        //清理上次的结果
        this->result_text.clear();

        this->call_SetSubKey();

        size_t dataLen = this->plain_text.size();
        if (dataLen % 8) {
            //若有余数,就需要填0
            //这种处理方法本身其实不安全,但是为了简便一些,不然加解密的时候还要考虑尾块的问题
            //这里主要是为了对齐并保证不遗漏
            while (this->plain_text.size() % 8)
            {
                this->plain_text.push_back(0);
            }

        }
        dataLen = this->plain_text.size();
        if (this->Is3DES) {
            //3次DES加密:加密(Key0)-解密(key1)-加密(Key0),解密:解密(key0)-加密(key1)-解密(key0)
            std::string Out;
            Out.resize(8);
            std::string In;
            for (size_t i{}, j = dataLen >> 3; i < j; i++) {
                Out.resize(8, 0);
                if (Type == ENCRYPT) {
                    //加密
                    In = this->plain_text.substr(i * 8, (i + 1) * 8);
                }
                else
                {
                    //解密
                    In = this->cipher_text.substr(i * 8, (i + 1) * 8);
                }
                DES(Out, In, this->subKey[0], Type);
                /*std::cout << "Out1:";
                for (int i{}; i < 8; i++) {
                    std::cout << static_cast<int>(Out[i]) << ",";
                }
                std::cout << std::endl;*/
                DES(Out, Out, this->subKey[1], Type == ENCRYPT ? DECRYPT : ENCRYPT);
                /*std::cout << "Out2:";
                for (int i{}; i < 8; i++) {
                    std::cout << static_cast<int>(Out[i]) << ",";
                }
                std::cout << std::endl;*/

                DES(Out, Out, this->subKey[0], Type);
                /*std::cout << "Out3:";
                for (int i{}; i < 8; i++) {
                    std::cout << static_cast<int>(Out[i]) << ",";
                }
                std::cout << std::endl;*/
                this->result_text.insert(this->result_text.end(), Out.begin(), Out.end());
                //std::cout << "Out字符串长度:" << Out.size() << "\tresult_text字符串长度" << this->result_text.size() << "\n";
                //this->result_text += Out;
                Out.clear();
            }
            if (Type == ENCRYPT) {
                //加密
                this->cipher_text = this->result_text;
            }
        }
        else {
            //1次des
            std::string Out;
            std::string In;
            //std::string result_text_temp = this->cipher_text;
            //this->result_text.clear();
            for (size_t i{}, j = dataLen >> 3; i < j; i++) {
                Out.resize(8,0);
                if (Type == ENCRYPT) {
                    //加密
                    In=this->plain_text.substr(i * 8, (i + 1) * 8);
                }
                else
                {
                    //解密
                    In = this->cipher_text.substr(i * 8, (i + 1) * 8);
                }
                DES(Out, In, this->subKey[0], Type);
                this->result_text.insert(this->result_text.end(), Out.begin(), Out.end());
                Out.clear();
            }
            if (Type == ENCRYPT) {
                //加密
                this->cipher_text = this->result_text;
            }
        }
    }
    else {
        return false;
    }
}
View Code

main

// DES和3DES算法实现.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "DES_C.h"
#include "DES_3.h"



int main()
{
    //char plain_text[10240] = { "2022年9月3日14:58:48" };        //设置明文

    //char key[100] = { "C/C++" };                        //设置秘钥

    //char encrypt_text[10240]{ 0 };                    //密文
    //char decrypt_text[10240]{ 0 };                    //解密文
    //printf("明文:%s\n", plain_text);

    ////DES加密
    ////DES_Act(encrypt_text, plain_text, sizeof(plain_text), key, strlen(key), ENCRYPT);
    //DES_Act(encrypt_text, plain_text, sizeof(plain_text), key, sizeof(key), ENCRYPT);

    //printf("DES加密后的密文:%s\n", encrypt_text);
    ////DES解密
    ////DES_Act(decrypt_text, encrypt_text, sizeof(plain_text), key, strlen(key), DECRYPT);
    //DES_Act(decrypt_text, encrypt_text, sizeof(plain_text), key, sizeof(key), DECRYPT);
    //printf("DES解密后的密文:%s\n", decrypt_text);

    //printf("\n\n\n\n\n");

    DES_3 des3;
    des3.setKey("C/C++++++++++++\n++++++++++++");
    std::string plainText = "DES_Act(decrypt_text, encrypt_text, sizeof(plain_text), key, sizeof(key), DECRYPT);";
    des3.set_plain_text(plainText);
    des3.DES_Act(DES_3::ENCRYPT);
    printf("DES加密后的密文:%s\n", des3.get_result_text());
    des3.DES_Act(DES_3::DECRYPT);
    printf("DES解密后的明文:%s\n", des3.get_result_text());
}
View Code

 

posted on 2022-09-06 16:31  狂自私  阅读(87)  评论(0编辑  收藏  举报