DES加密解密算法(简单、易懂、超级详细)

news2024/7/6 18:23:31

目录

一、基础补充

二、什么是DES算法

    (1)对称加密算法

    (2)非对称加密算法

    (3)对称加密算法的应用

三、DES算法的基础操作步骤

    1.明文的加密整体过程

    2.F轮函数解析

    3.密钥的形成过程

四、AC代码

五、DES算法的测试

 六、共勉


一、基础补充

    在实现DES算法时,需要掌握对二进制数的了解,例如:源码、反码、补码,位操作等,如果有不懂的朋友可以先去看看我对二进制数的理解,再来看DES算法,会更加容易。

    源码、反码、补码:http://t.csdn.cn/Osuf2

    位操作,例如:按位与、按位或、按位异或、按位左移、按位右移等:http://t.csdn.cn/YQ60C

    我的参考视频:

DES加密算法|密码学|信息安全_哔哩哔哩_bilibili

二、什么是DES算法

    (1)对称加密算法

    1. 通信的双方同时掌握一个密钥,加密解密都是由一个密钥完成的(加密密钥等于解密密钥)。

    2. 双方通信前共同拟定一个密钥,不对第三方公开。

    3. 不具有个体原子性,一个密钥被共享,泄露几率会大大增加。

    (2)非对称加密算法

    1.在非对称加密中,不再只有一个密钥Key了。在非对称加密算法中,密钥被分解为一对,一个称为公开密钥,另一个称为私有密钥。对于公钥,可以通过非保密方式向他人公开,而私钥则由解密方保密,不对别人公开。

    (3)对称加密算法的应用

    1. DES算法是对称加密算法的代表,虽然现在已经很好实现,但是对于研究其改进的方法,有很重大的影响。

    2. 在DES算法中由于大部分原始数据较长,首先需要将数据切成64位的明文分组,所以DES算法也叫做分组加密算法。

    3. 在DES算法中使用的密钥位64位,其中有效的密钥长度其实只有56位(分成8块每块长为8位,每隔8位设置左后一位为校验位,采用就奇偶校验法)。

    4. 在DES算法中加密的明文较长,需要对DES加密进行16轮的函数循环迭代。

三、DES算法的基础操作步骤

    由于DES算法过于复杂,我将它分为3大步:

    (1)明文的加密的整体过程

    (2)F轮函数解析

    (3)密钥的形成过程

    1.明文的加密整体过程

    (1)  输入64bit的明文进行IP置换,分成左右两个分支各为32bit, 左边:32bitL0,右边:32bitR0

      (2)  右分支:L1 = R0  左分支:引入48bit 的密钥,R1=L0 异或  f(R0,K1)  

      (3)  相同的操作进行16次的运算循环,算出相应的,R1~R16,L0~L16

    (4)最后在进行IP的逆序置换,将左右两个分支再次合并为64bit密文

    (5)将上述的说法,汇聚成流程图,方便大家理解

     (6)整体的操作代码:

string wen(string wenBinary[], int num)
{
    int i, j;
    string ipWenBinary[100];  //保存明文
    string left[17], right[17], temp, result; //分为左右两个分支
    for (i = 0; i < num; i++)
    {
        temp = ""; //一个暂存明文的字符串
        //进行IP置换
        for (j = 0; j < 64; j++)  //明文为64bit
        {
            temp += wenBinary[i][ipTable[j] - 1];
        }
        ipWenBinary[i] = temp;
    }
    //进行左右分支,分为left:L0,,,right:R0
    for (i = 0; i < num; i++)
    {
        left[0] = ipWenBinary[i].substr(0, 32);
        right[0] = ipWenBinary[i].substr(32, 32);
        //
        for (j = 0; j < 16; j++)   //进行16次循环
        {
            left[j + 1] = right[j];   //  left: L1 = R0
            //加密和解密的区别
            // flag 为全局变量
            if (flag == 1) // flage = 1进行加密,否则进行解密
                right[j + 1] = xorAB(left[j], f(right[j], k[j]));
            else
                //倒着进行解密
                right[j + 1] = xorAB(left[j], f(right[j], k[15 - j]));
        }
        temp = right[j] + left[j];  //经过16轮加密/解密,将左右32bit合并
        //将加密后的密文进行最后的置换,实际上和初始置换是对称的~!
        //每块的加密结果都和在result中,加密可以直接输出比特流
        // 进行IP的逆置换
        for (j = 0; j < 64; j++)
        {
            result += temp[ipReverseTable[j] - 1];
        }
    }
    //解密结果输出的是字符
    if (flag == 2)
    {
        string ch;
        for (i = 0; i < num * 8; i++) //一个模块是8个bit
        {
            ch += binaryToInt(result.substr(8 * i, 8)); //每8bit进行一次二进制转整型
        }
        result = ch;
    }
    return result;
}

     (7)在以上的操作都是在进行二进制数、整数、字符转换,操作代码如下:

//字符转二进制
string charToBinary(char c)
{
    int i, b = c, k = 0, flag = 0;
    string result;
    //负数就是中文字符
    if (b < 0)
    {
        b = -b;
        flag = 1;
    }
    //英文字符转换成ASCII的倒序,所以后面需要进行逆序
    while (k < 8) //这里的8表示char是1个字节=8bit
    {
        if (b) //这里将ASCII里的字符转换为二进制
        {
            result += ((b % 2) + '0');  // 其中这里+'0',表示将数字转换为字符
            b /= 2;
        }
        else result += '0';
        k++;
    }
    //汉字字符处理
    if (flag)//判断是否为汉字
    {
        for (i = 0; i < result.length(); i++)   //此时因为是负数,源码、反码、补码不相等,需要置换
        {
            if (result[i] == '0') result[i] = '1';  // 反码:最高最不变,其它的0->1,,1->0
            else result[i] = '0';
        }
        for (i = 0; result[i] != '0'; i++)
        {
            result[i] = '0';              //补码 :反码加+1
        }
        result[i] = '1';
    }
    reverse(result.begin(), result.end());  //将结果逆序,成为最终的二进制
    return result;
}
//二进制转整型
int binaryToInt(string s)
{
    int i, result = 0, p = 1;
    for (i = s.length() - 1; i >= 0; i--)
    {
        result += ((s[i] - '0') * p);   //数字字符转成字符
        p *= 2;
    }
    return result;
}
//整型转二进制
string intToBinary(int i)
{
    int k = 0;
    string result;
    while (k < 4) //此处,处理进入S盒后取出的数据转为2进制,此处最多用4bit

    {
        if (i)
        {
            result += ((i % 2) + '0');
            i /= 2;
        }
        else result += '0';
        k++;
    }
    reverse(result.begin(), result.end());
    return result;
}

2.F轮函数解析

    F轮函数是整个DES算法的核心其中包括:

    (1)IP置换

    (2)E扩展:将32bit的R0扩展为48bit的R0,其中扩展图为:

    (3)异或:将48bit的R0于48bit的K1进行异或

    (4)S盒压缩处理 :大盒子里有8块6bit 的小盒子,刚好容纳48bit的二进制数,盒子的特点是6进4出,出了盒子就变成了32bit的二进制数,举例:

     (5)IP逆序置换

    其中F轮函数的执行代码如下图所示:

//f函数
string f(string right, string k) //其中right 为明文的右分支R0--R16,k当前加密轮密钥
{
    int i, temp;
    string extendBinary, result, b0; //extendBinary用来存放E扩展32bit~48bit的内容
    string b[8], row, col;
    string b8, pb;
    for (i = 0; i < 48; i++)
    {
        extendBinary += right[extendTable[i] - 1];
    }
    b0 = xorAB(extendBinary, k);//扩展后的内容与此轮密钥异或操作并将结果存入b0中
    for (i = 0; i < 8; i++)  //将b0的内容分成八份,每份六bit,为进入S盒做准备
    {
        b[i] = b0.substr(i * 6, 6);
    }
    for (i = 0; i < 8; i++)
    {
        //6bit的第一位和第六位作为行坐标
        row = b[i].substr(0, 1) + b[i].substr(5, 1);
        //6bit的第二至五位作为纵坐标
        col = b[i].substr(1, 4);
        //进行查表
        temp = sBox[i][binaryToInt(row)][binaryToInt(col)];
        //转到b8中合并----48bit压缩到32bit
        b[i] = intToBinary(temp);
        b8 += b[i];
    }
    //进行P盒置换
    for (i = 0; i < 32; i++)
    {
        pb += b8[pTable[i] - 1];
    }
    //f轮函数结束,返回pb
    return pb;
}

3.密钥的形成过程

    (1)密钥原本为64bit ,去掉8位校验位,剩余56位参与运算

    (2)按照交换规则,生成16位48bit的轮密钥

    其中密钥生成的流程图和代码如下图: 

void miyao()
{
    int i, j;
    string miyao, miyaoBinary, pc1MiyaoBinary;
    string c[17], d[17], temp, pc2Temp;
    cout << "请输入密钥:";
    while (cin >> miyao)
    {
        if (miyao.length() < 9) break;
        else cout << "密钥不能超过8位,请重新输入:";
    }
    for (i = 0; i < miyao.length(); i++)
    {
        miyaoBinary += charToBinary(miyao[i]);
    }
    //密钥长度不足64bit,补'0'
    //64位中,只有56位参与运算,其中8位为校验位
    while (miyaoBinary.length() % 64 != 0)
    {
        miyaoBinary += '0';
    }
    //从64bit密钥中依据PC-1盒子取出56bit
    for (i = 0; i < 56; i++)
    {
        pc1MiyaoBinary += miyaoBinary[pc1Table[i] - 1];
    }
    //56bit分成左右两部分
    // 左右两部分都为28bit
    c[0] = pc1MiyaoBinary.substr(0, 28);
    d[0] = pc1MiyaoBinary.substr(28, 28);
    产生16轮加密需要的密钥,存入全局变量k[]中
    for (i = 1; i <= 16; i++)
    {
        //根据循环移位表,确定生成该轮密钥移位数目
        c[i] = c[i - 1].substr(loopTable[i - 1], 28 - loopTable[i - 1]) + c[i - 1].substr(0, loopTable[i - 1]);
        d[i] = d[i - 1].substr(loopTable[i - 1], 28 - loopTable[i - 1]) + d[i - 1].substr(0, loopTable[i - 1]);
        //移位后将其合并
        temp = c[i] + d[i];
        pc2Temp = "";
        // 通过PC2成为48bit密钥
        for (j = 0; j < 48; j++)
        {
            pc2Temp += temp[pc2Table[j] - 1];
        }
        k[i - 1] = pc2Temp;//从1`16
    }
}

四、AC代码

(1)先建立一个#include "DES.h"的头文件,放入需要的函数

#pragma once
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
//字符转二进制
string charToBinary(char c);
//二进制转整型
int binaryToInt(string s);
//整型转二进制
string intToBinary(int i);
//异或运算
string xorAB(string a, string b);
//f函数
string f(string right, string k);
//明文/密文处理
string wen(string wenBinary[], int num);
//密钥处理
void miyao();
//DES 算法测试
void DES();


(2)在建立DES.cpp,写出头文件中对应的函数操作

#define  _CRT_SECURE_NO_WARNINGS 1
#include "DES.h"
//进行标记选择
int flag;
string k[16]; //16轮密钥存储
//PC1选位表
int pc1Table[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
};
//左移位数表
int loopTable[16] =
{
    1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};
//PC2选位表
int pc2Table[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
};
//置换IP表
int ipTable[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
};
//E扩展置换表
int extendTable[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
};
//S盒
int sBox[8][4][16] =
{
    //S1
    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,
    //S2
    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,
    //S3
    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,
    //S4
    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,
    //S5
    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,
    //S6
    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,
    //S7
    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,
    //S8
    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
};
//P换位表
int pTable[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
};
//逆置换IP^-1表
int ipReverseTable[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
};
//将输入的东西全部看成字符
//字符转二进制
string charToBinary(char c)
{
    int i, b = c, k = 0, flag = 0;
    string result;
    //负数就是中文字符
    if (b < 0)
    {
        b = -b;
        flag = 1;
    }
    //英文字符转换成ASCII的倒序,所以后面需要进行逆序
    while (k < 8) //这里的8表示char是1个字节=8bit
    {
        if (b) //这里将ASCII里的字符转换为二进制
        {
            result += ((b % 2) + '0');  // 其中这里+'0',表示将数字转换为字符
            b /= 2;
        }
        else result += '0';
        k++;
    }
    //汉字字符处理
    if (flag)//判断是否为汉字
    {
        for (i = 0; i < result.length(); i++)   //此时因为是负数,源码、反码、补码不相等,需要置换
        {
            if (result[i] == '0') result[i] = '1';  // 反码:最高最不变,其它的0->1,,1->0
            else result[i] = '0';
        }
        for (i = 0; result[i] != '0'; i++)
        {
            result[i] = '0';              //补码 :反码加+1
        }
        result[i] = '1';
    }
    reverse(result.begin(), result.end());  //将结果逆序,成为最终的二进制
    return result;
}
//二进制转整型
int binaryToInt(string s)
{
    int i, result = 0, p = 1;
    for (i = s.length() - 1; i >= 0; i--)
    {
        result += ((s[i] - '0') * p);   //数字字符转成字符
        p *= 2;
    }
    return result;
}
//整型转二进制
string intToBinary(int i)
{
    int k = 0;
    string result;
    while (k < 4) //此处,处理进入S盒后取出的数据转为2进制,此处最多用4bit

    {
        if (i)
        {
            result += ((i % 2) + '0');
            i /= 2;
        }
        else result += '0';
        k++;
    }
    reverse(result.begin(), result.end());
    return result;
}
//异或运算
string xorAB(string a, string b)
{
    int i;
    string result;
    for (i = 0; i < a.length(); i++)
    {                                           //+'0':表示数字转化为数字字符
        result += (((a[i] - '0') ^ (b[i] - '0')) + '0');  // -'0':表示数字字符转化为数字
    }
    return result;
}
//f函数
string f(string right, string k) //其中right 为明文的右分支R0--R16,k当前加密轮密钥
{
    int i, temp;
    string extendBinary, result, b0; //extendBinary用来存放E扩展32bit~48bit的内容
    string b[8], row, col;
    string b8, pb;
    for (i = 0; i < 48; i++)
    {
        extendBinary += right[extendTable[i] - 1];
    }
    b0 = xorAB(extendBinary, k);//扩展后的内容与此轮密钥异或操作并将结果存入b0中
    for (i = 0; i < 8; i++)  //将b0的内容分成八份,每份六bit,为进入S盒做准备
    {
        b[i] = b0.substr(i * 6, 6);
    }
    for (i = 0; i < 8; i++)
    {
        //6bit的第一位和第六位作为行坐标
        row = b[i].substr(0, 1) + b[i].substr(5, 1);
        //6bit的第二至五位作为纵坐标
        col = b[i].substr(1, 4);
        //进行查表
        temp = sBox[i][binaryToInt(row)][binaryToInt(col)];
        //转到b8中合并----48bit压缩到32bit
        b[i] = intToBinary(temp);
        b8 += b[i];
    }
    //进行P盒置换
    for (i = 0; i < 32; i++)
    {
        pb += b8[pTable[i] - 1];
    }
    //f轮函数结束,返回pb
    return pb;
}
//明文/密文处理
string wen(string wenBinary[], int num)
{
    int i, j;
    string ipWenBinary[100];  //保存明文
    string left[17], right[17], temp, result; //分为左右两个分支
    for (i = 0; i < num; i++)
    {
        temp = ""; //一个暂存明文的字符串
        //进行IP置换
        for (j = 0; j < 64; j++)  //明文为64bit
        {
            temp += wenBinary[i][ipTable[j] - 1];
        }
        ipWenBinary[i] = temp;
    }
    //进行左右分支,分为left:L0,,,right:R0
    for (i = 0; i < num; i++)
    {
        left[0] = ipWenBinary[i].substr(0, 32);
        right[0] = ipWenBinary[i].substr(32, 32);
        //
        for (j = 0; j < 16; j++)   //进行16次循环
        {
            left[j + 1] = right[j];   //  left: L1 = R0
            //加密和解密的区别
            // flag 为全局变量
            if (flag == 1) // flage = 1进行加密,否则进行解密
                right[j + 1] = xorAB(left[j], f(right[j], k[j]));
            else
                //倒着进行解密
                right[j + 1] = xorAB(left[j], f(right[j], k[15 - j]));
        }
        temp = right[j] + left[j];  //经过16轮加密/解密,将左右32bit合并
        //将加密后的密文进行最后的置换,实际上和初始置换是对称的~!
        //每块的加密结果都和在result中,加密可以直接输出比特流
        // 进行IP的逆置换
        for (j = 0; j < 64; j++)
        {
            result += temp[ipReverseTable[j] - 1];
        }
    }
    //解密结果输出的是字符
    if (flag == 2)
    {
        string ch;
        for (i = 0; i < num * 8; i++) //一个模块是8个bit
        {
            ch += binaryToInt(result.substr(8 * i, 8)); //每8bit进行一次二进制转整型
        }
        result = ch;
    }
    return result;
}
//密钥处理
void miyao()
{
    int i, j;
    string miyao, miyaoBinary, pc1MiyaoBinary;
    string c[17], d[17], temp, pc2Temp;
    cout << "请输入密钥:";
    while (cin >> miyao)
    {
        if (miyao.length() < 9) break;
        else cout << "密钥不能超过8位,请重新输入:";
    }
    for (i = 0; i < miyao.length(); i++)
    {
        miyaoBinary += charToBinary(miyao[i]);
    }
    //密钥长度不足64bit,补'0'
    //64位中,只有56位参与运算,其中8位为校验位
    while (miyaoBinary.length() % 64 != 0)
    {
        miyaoBinary += '0';
    }
    //从64bit密钥中依据PC-1盒子取出56bit
    for (i = 0; i < 56; i++)
    {
        pc1MiyaoBinary += miyaoBinary[pc1Table[i] - 1];
    }
    //56bit分成左右两部分
    // 左右两部分都为28bit
    c[0] = pc1MiyaoBinary.substr(0, 28);
    d[0] = pc1MiyaoBinary.substr(28, 28);
    产生16轮加密需要的密钥,存入全局变量k[]中
    for (i = 1; i <= 16; i++)
    {
        //根据循环移位表,确定生成该轮密钥移位数目
        c[i] = c[i - 1].substr(loopTable[i - 1], 28 - loopTable[i - 1]) + c[i - 1].substr(0, loopTable[i - 1]);
        d[i] = d[i - 1].substr(loopTable[i - 1], 28 - loopTable[i - 1]) + d[i - 1].substr(0, loopTable[i - 1]);
        //移位后将其合并
        temp = c[i] + d[i];
        pc2Temp = "";
        // 通过PC2成为48bit密钥
        for (j = 0; j < 48; j++)
        {
            pc2Temp += temp[pc2Table[j] - 1];
        }
        k[i - 1] = pc2Temp;//从1`16
    }
}
// 输出函数
void DES()
{
    int i, j, num;
    string wenString, wenBinary[100], temp;
    while (1)
    {
        cout << "----------------------------------------------" << endl;
        cout << "*****     请选择所需功能: *****" << endl;
        cout << "*****       1. 加密        *****" << endl;
        cout << "*****       2. 解密        *****" << endl;
        cout << "*****       0.退出程序     *****"<< endl;
        cout << "----------------------------------------------" << endl;
        cin >> flag;
        if (!flag) 
            break;
        else if ((flag != 1) && (flag != 2))
        {
            cout << "输入不合法,请重新输入!" << endl << endl;
            continue;
        }
        num = 0;
        miyao();
        getchar();
        switch (flag)
        {
        case 1:
            cout << "请输入明文:";
            getline(cin, wenString);//输入明文
            //将明文转成二进制
            for (i = 0; i < wenString.length(); i++)
            {
                temp += charToBinary(wenString[i]);
                //字符每满8bit为一组,最后一组可以不满8bit,后面会补0
                if (((i + 1) % 8 == 0) || (((i + 1) % 8 != 0) && (i == wenString.length() - 1)))
                {
                    wenBinary[num++] = temp;
                    temp = "";
                }
            }
            //最后一组不满64位就补零,补的零,一定是八的整数倍,二进制00000000为null空字符,不输出
            while (wenBinary[num - 1].length() % 64 != 0)
            {
                wenBinary[num - 1] += '0';
            }
            cout << "加密结果为(二进制):" << wen(wenBinary, num) << endl << endl;
            break;
        case 2:
            cout << "请输入密文(二进制):";
            cin >> wenString;
            for (i = 0; i * 64 < wenString.length(); i++)
            {
                wenBinary[num++] = wenString.substr(i * 64, 64);
            }
            cout << "解密结果为(字符):" << wen(wenBinary, num) << endl << endl;
            break;
        case 3:
            exit(0);
        default :
            cout << "输入错误,请重新输入" << endl;
        }
    }
}

(3)最后在test.c中测试就可以啦!

#define  _CRT_SECURE_NO_WARNINGS 1
#include "DES.h"
void menu()
{
    cout << "**********************************************" << endl;
    cout << "**********************************************" << endl;
    cout << "***********欢迎来到DES加密测试系统************" << endl;
    cout << "**********************************************" << endl;
    cout << "**********************************************" << endl;
}
int main()
{
    menu();
    DES();
    return 0;
}

五、DES算法的测试

 六、共勉

    这篇就是我对DES加密解密算法的理解,如果有不懂或者有问题的小伙伴可以在评论区里说出来哦,我们一起加油哦!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1649739.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自然语言(NLP)

It’s time for us to learn how to analyse natural language documents, using Natural Language Processing (NLP). We’ll be focusing on the Hugging Face ecosystem, especially the Transformers library, and the vast collection of pretrained NLP models. Our proj…

JuiceFS v1.2-beta1,Gateway 升级,多用户场景权限管理更灵活

JuiceFS v1.2-beta1 今天正式发布。在这个版本中&#xff0c;除了进行了大量使用体验优化和 bug 修复外&#xff0c;新增三个特性&#xff1a; Gateway 功能扩展&#xff1a;新增了“身份和访问管理&#xff08;Identity and Access Management&#xff0c;IAM&#xff09;” 与…

WHM中如何查看磁盘使用情况

今日看到有用户在论坛留言反馈他买了Hostease 独立服务器并购买cPanel面板&#xff0c;想要通过面板查看当前服务器使用的磁盘情况&#xff0c;但是不知道如何查看。因为这边也是对于cPanel即WHM面板有是有所了解的&#xff0c;对于这个用户的问题&#xff0c; 操做步骤如下&am…

【Linux】Docker 安装部署 Nacos

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 【Linux】Docker 安装部署 Nacos docker搜索na…

看完这篇文章我奶奶都懂Opentracing了(一)

前言 如果要基于Opentracing开发分布式链路追踪Java客户端工具包&#xff0c;首先肯定需要了解Opentracing中的各种概念&#xff0c;包括但不限于Span和Scope等&#xff0c;其实这些概念在Opentracing的官方文档中是有比较详尽的说明的&#xff0c;英文不好也能靠着机器翻译读…

【linux-IMX6ULL中断配置流程】

目录 1. Cortex-A7和GIC中断概述1. 1 Cortex-A7中断系统&#xff1a;1. 2 GIC中断控制器简介&#xff1a; 2. 中断配置概述3. 底层中断文件配置3.1 对启动文件.s的配置思路3.2 对中断函数配置思路 4. 上层中断配置流程 1. Cortex-A7和GIC中断概述 学习IMX6UL的中断处理系统&…

毕业就业信息|基于Springboot+vue的毕业就业信息管理系统的设计与实现(源码+数据库+文档)

毕业就业信息管理系统 目录 基于Springboot&#xff0b;vue的毕业就业信息管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1学生信息管理 2 公司信息管理 3公告类型管理 4公告信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设…

自动化运维管理工具 Ansible-----【inventory 主机清单和playbook剧本】

目录 一、inventory 主机清单 1.1inventory 中的变量 1.1.1主机变量 1.1.2组变量 1.1.3组嵌套 二、Ansible 的脚本 ------ playbook&#xff08;剧本&#xff09; 2.1 playbook介绍 2.2playbook格式 2.3playbooks 的组成 2.4playbook编写 2.5运行playbook 2.5.1ans…

如何翻译外文文献【攻略】

如何翻译外文文献【攻略】 前言版权推荐如何翻译外文文献简单描述第一步 准备一篇外文文献第二步 翻译网站第三步 解锁文档第四步 编辑dpf第五步 pdf转为word第六步 编辑word方便操作快捷键设置章节设置页眉页脚设置页码三线表的绘制 第七步 word转为pdf 最后 前言 2024-5-7 1…

电脑提示“无法定位程序输入点kernel32.dll”怎么解决?分享kernel32.dll丢失的五个修复方法

打开游戏或者软件的时候&#xff0c;电脑提示由于找不到kernel32.dll&#xff0c;无法继续执行此代码怎么办&#xff0c;其实修复起来不难。首先需要先知道怎么是dll文件&#xff0c;dll文件可以简单的把库文件看成一种代码仓库&#xff0c;它提供给使用者一些可以直接拿来用的…

【SSM进阶学习系列丨分页篇】PageHelper 分页插件集成实践

文章目录 一、说明什么是分页PageHelper介绍 二、导入依赖三、集成Spring框架中四、编写Service五、编写Controller六、编写queryAllByPage页面展示数据 一、说明 什么是分页 ​ 针对分页&#xff0c;使用的是PageHelper分页插件&#xff0c;版本使用的是5.1.8 。 ​ 参考文档…

openEuler 22.03 GPT分区表模式下磁盘分区管理

目录 GPT分区表模式下磁盘分区管理parted交互式创建分区步骤 1 执行如下步骤对/dev/sdc磁盘分区 非交互式创建分区步骤 1 输入如下命令直接创建分区。 删除分区步骤 1 执行如下命令删除/dev/sdc1分区。 GPT分区表模式下磁盘分区管理 parted交互式创建分区 步骤 1 执行如下步骤…

Day 24 数据库管理及数据类型

数据库管理及数据类型 一&#xff1a;数据类型 1.数值类型 整数类型 ​ 整数类型&#xff1a;TINYINT SMALLINT MEDIUMINT INT BIGINT ​ 作用&#xff1a;用于存储用户的年龄、游戏的Level、经验值等 浮点数类型 ​ 浮点数类型&#xff1a;FLOAT DOUBLE ​ 作用&#xf…

2024 cleanmymac有没有必要买呢,全反面分析

在使用mac时&#xff0c;小编遇到了运行内存不足、硬盘空间不足的情况。遇到这种情况&#xff0c;我们可以借助经典的电脑深度清理软件——CleanMyMac X&#xff0c;清理不常用的软件和系统垃圾&#xff0c;非常好用&#xff01;不过&#xff0c;有许多网友发现CleanMyMac X有免…

基于Springboot的校园新闻管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的校园新闻管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

NFTScan 与 Scattering 达成合作伙伴,双方将共同解决混合 NFT 数据需求

在区块链领域&#xff0c;NFT 的创新与发展从未停止。近日&#xff0c;NFT 数据基础设施 NFTScan 与一站式混合 NFT 交易市场 Scattering 达成合作伙伴关系&#xff0c;双方将在 NFT 数据层面展开合作&#xff0c;共同解决混合 NFT 的独特数据需求&#xff0c;Scattering 在协议…

非平衡数据处理-Tomek link算法介绍,代码和实战测评

作者Toby&#xff0c;来源公众号&#xff1a;Python风控模型&#xff0c;非平衡数据处理-Tomek link算法 概述 非平衡数据在金融风控领域、反欺诈客户识别、广告智能推荐和生物医疗中普遍存在。一般而言&#xff0c;不平衡数据正负样本的比例差异极大&#xff0c;如在Kaggle竞…

Quora 首席执行官亚当·德安杰洛 (Adam D’Angelo) 谈论了 AI、聊天机器人平台 Poe,以及 OpenAI 为什么不是竞争对手

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

无线通信基础

这里写目录标题 通信概述什么是无线通信无线通信电磁波 通信概述 什么是无线通信 无线通信 : 是指利用电磁波信号可以在自由空间中传播的特性进行信息交换的一种通信方式 无线通信的关键技术包括调制技术、解调技术、信道编码技术、信号处理技术、天线技术等。这些技术的不断…