基于C++的DES的EBC电子密码本加解密,CBC密码分组链接思想,以及相关流程图

CBC模式的DES加解密

一、实验内容

学习并完成对称加解密中的DES加解密以及CBC模式的DEC加解密。

二、实验原理

2.1 DES加解密原理

DES算法是一种最通用的对称密钥算法,因为算法本身是公开的,所以其安全性在于密钥的安全性。基于密钥的算法通常有两类:对称算法和公开密钥算法。对称算法的对称性体现在加密密钥能够从解密密钥推算出来,反之亦然。在大多数对称算法中,加解密的密钥是相同的,DES就是这样。对称密钥算法的加解密密钥都是保密的。

Des流程图
在这里插入图片描述
Des加密主要可以分为四个步骤:1.初始置换。2.密钥的运算。3.密码函数的运算。4.逆置换。
初始置换和为逆置换都是根据置换表进行的,复杂的地方在于密码的获得和函数f的运算。

初始置换表:
在这里插入图片描述
逆置换表:
在这里插入图片描述
密码获得:
1.我们在读入64位原密码后首先会根据置换表一进行第一次压缩置换,将64位密码中的标志位去除,得到56位的原密码。
2.下一步我们将剩余的56位原密码左边28位标为C0,右边28位标为D0,根据左移规则进行循环左移后得到C1和D1,将C1,D1合起来进行压缩置换2,得到48位的密钥k1。
3.接下来的步骤就可以进行循环处理,将第二步得到的C1,D1再次按规则进行循环左移得到C2和D2,再次进行压缩置换2得到48位的密钥k2,之后的k3–k16依次如此获得。

**轮函数的运转:**轮函数为{Li=Ri-1;Ri=Li-1^f(ki,Ri-1),i=1,2,16}。这里R0指64位明文的后32位,L0指64位明文的前32位,我们可以看到Li是可以很方便得到的,但是轮函数F很复杂,我们可以分为以下步骤进行。
1.我们将输入进来的32位Ri-1进行扩展置换,得到48位的一组数。
2.将这个48位的数与对应的48位密钥进行异或运算之后得到新48位的数。再将这48位分成8组,每组6位,放入对应的S盒进行6–>4位的转换(第一位和第六位组合起来是行数,中间四位组合起来是列数),得到32位数据,将这32位数据进行p盒置换之后,就得到轮函数结果。
3.再和Li-1进行异或即可得到Ri。

2.2 3DES加解密原理

我们在得到des加密模块之后,就可以很方便的进行3des加密,3des加密不是指加密三次,而是指第一次调用加密des函数进行运算,第二次调用解密des函数进行运算,第三次在进行加密des,三次的密钥都不一样的,我们可以单独在主函数调用三次这个模块。
3DES加密过程为:C=Ek3(Dk2(Ek1§))
3DES解密过程为:P=Dk1((EK2(Dk3©))
3DES:trip DES(3级DES,是DES的升级版,主要是为了应对快速发展的计算机能力,能够在24小时内暴力破解传统的56位长度密钥的DES,而3DES相当于对统一数据块采用3次DES,3次DES使用的密钥如果完全不同,则密钥长度可以达到168位,大大延长了被暴力破解的时间)

2.3 分组密码CBC加解密模式原理

CBC模式是指:大部分的加解密流程和EBC电子密码本一样,不同的是每个明文组在加密前与前一组密文按位异或运算后,再进行加密变换。第一组加密时有一个初始向量IV,第一组和这个初始向量IV异或运算。采用CBC方式加密时,双方不仅要共享加解密密钥,还要共享初始向量IV,解密时每组密文先进行解密,再与前一组密文进行异或运算,还原出明文。
使用CBC模式加解密时,初始换向量IV和密钥一样重要,在加密时由于引入反馈机制,所以不能进行并行运算处理,同时,相同的明文在相同的密钥下,也会得到不同的密文分组,CBC模式隐藏了明文的统计特性,且如果密文分组里的一个比特错误,就会影响到本组和其后的每一个分组的解密。

CBC模式加密流程图:
在这里插入图片描述

CBC模式解密流程图:
在这里插入图片描述

2.4 填充原理

对称加密中的分组加解密都有一个问题,就是在分组的时候最后的那一组可能不会刚好为一组,所以我们需要进行填充处理,填充处理分为两种情况,第一种是刚好分为完整的一组,第二种为不满一组的情况,一般第二种较多。策略如下:
1.刚好分为一组的时候:刚好分为一组时,我们单独加一个分组,全部设为0。
2.当一个分组不够时,我们补齐8个,最后一个为补充的个数,比如@@@,差5个我们就补充为@@@00005。

三、实验过程

3.1 变量说明

3.1.1 主函数变量说明
Int y//几DES加密选择
Int X//主函数加解密选择
String mingwenfile//明文的文件地址
String miyaofile//密钥的文件地址
String miwenfile//密文的文件地址
String jmmingwenfile//解密后的明文文件地址

3.1.2 其他重要变量说明

  1. encrypt // 函数中加密选择
  2. decrypt//函数中解密选择
  3. Pad//填充,数据长度不足8byte的倍数时,以0x00补足,如果是8byte的倍数,补8个0x00。
  4. const char IP_Table[64] //初始置换ip,将读入的明文串进行特定顺序重排,之后将前32位和后32位分别记为L0和R0。
  5. const char IPR_Table[64]// 初始置换ip-1,将最终得到的R16,I16进行初始置换的逆置换后得到。
  6. const char E_Table[48]//扩展置换,在计算轮函数时将32位输入扩展位48位,在与子密钥进行安位模2加运算。
  7. const char P_Table[32]//p盒置换。
  8. const char PC1_Table[56]//置换选择一,去掉标识位。
  9. const char PC2_Table[48]//置换选择二,将循环左移之后的56位进行置换选择二得到48位,即为密钥Ki。
  10. const char LOOP_Table[16]//生成子密钥时,生成Ci/Di时进行循环左移的位数。
  11. const char S_Box[8][4][16]//s盒,轮函数里生成s1到s8后再进行P盒置换就成轮函数f(Ri-1,Ki)。

3.2 函数功能说明
3.2.1主函数说明
主函数起到调用的作用,调用加解密模块以及选择几DES加密的功能。加解密的功能都在模块函数中实现。
3.2.2 其他重要函数说明(以下为举例)
1)char * CDES::HexToStr(string s)
作用:十六进制字符串转化为ASCII字符串 每2位十六进制字符 = 8 bit = 1 ASCII字符。
参数:需要转换成ASCLL字符串的十六进制字符串。
返回:转换后的字符串。

2)string CDES::StrToHex(char* bytes, int bytelength)
作用:字符串转化为十六进制 一个字符 = 一个ASCII码 = 两位十六进制数 。
参数:字符串,以及其长度。
返回:转换后的字符串。

3)static void zuoyi(bool *In, int len, int loop)
作用:按规则循环左移。
参数:需要读入的字符串,字符串长度,移动规则表。
返回:左移后的字符串。

4)static void Xor(bool *InA, const bool *InB, int len)
作用:两个bit流进行异或。
参数:bit流A和B,长度。
返回:异或后得到的串。

5)static void zhihuan(bool *Out, bool *In, const char *Table, int len)
作用: 把Bit流按表进行位转化。
参数:读入的bit流和输出的bit流,长度,需要置换的表。
返回:置换后的表。

6)void CDES::SetSubKey(PSubKey pSubKey, const unsigned char Key[8])
作用:计算密码并填充到pSubKey中。
参数:数组pSubKey,读入的8字节16进制数。
返回:将计算得到的结果存入密码数组中。

7)static void Sbox(bool Out[32], const bool In[48])
作用:s盒模块。
参数:读入的48位串,经过6–>4的处理的串。
返回:处理后的串。

8)static void lunhs(bool In[32], const bool Ki[48])
作用:轮函数模块。
参数:读入的32位Ri,48位密钥。
返回:处理好的串。

9)bool RunDES(bool bType, bool bMode, int PaddingMode, const unsigned char* In,unsigned char* Out, unsigned datalen, const unsigned char* Key, unsigned keylen)
作用:执行DES对算法进行加解密。
参数:bType:加解密类型;bMove:默认为1;in:待加密串指针;out:待传输串指针;datalen:待加密串长度;key:密钥。Keylen:密钥长度。
返回:成功或失败(true/false)。

10)bool RunPad(bool bType, int nType, const unsigned char* In, unsigned datalen, unsigned char* Out, unsigned& padlen)
作用:填充函数。
参数:nType:pad类型;in:数据串指针;out:填充输出串指针;datalen:数据长度;padlen:填充后的长度。
返回:返回处理成功或失败(true/false)。

11)bool CDES::EnCode(string mingwenfile,string miyaofile,string miwenfile)
作用:加密入口。
参数:文明、密钥、密文文件的地址。
返回:返回处理成功或失败(true/false)。

12)bool CDES::DeCode(string miyaofile,string miwenfile,string jmhmingwenfile)
作用:解密入口。
参数:密钥、密文、解密后明文的文件地址。
返回:返回处理成功或失败(true/false)。

3.3 流程图

3.3.1 主函数流程图
在这里插入图片描述

3.3.2 其他重要函数流程图

1.子密钥流程图:
在这里插入图片描述

2.轮函数流程图:
在这里插入图片描述
3.加密入口模块的流程图:
在这里插入图片描述
4.解密入口流程图:
在这里插入图片描述
5.选择界面流程图:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

四、实验结果与截图

1.选择界面
在这里插入图片描述
2.一次DES加解密:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.3DES加密:
在这里插入图片描述
**4.CBC模式加密:**在这里插入图片描述
在这里插入图片描述

5.CBC模式解密:
在这里插入图片描述

代码奉上

#include <bits/stdc++.h>
#include<fstream>
using namespace std;

class CDES {
public:
	CDES();
	virtual ~CDES();
	/*十六进制字符串转化为ASCII字符串  每2位十六进制字符 = 8 bit = 1 ASCII字符*/
	static char* HexToStr(string s);
	/*字符串转化为十六进制  一个字符 = 一个ASCII码 = 两位十六进制数 */
	static string StrToHex(char* bytes, int bytelength);
	//进行加密
	static bool EnCode(string q,string w,string e);
    static bool DeCode(string w,string e,string r);
protected:
	typedef bool(*PSubKey)[16][48];

	static bool RunDES(bool bType, bool bMode, int PaddingMode, const unsigned char* IV, const unsigned char* In,
		unsigned char* Out, unsigned datalen, const unsigned char* Key, unsigned keylen);


    static void DES(unsigned char Out[8], const unsigned char In[8], const PSubKey pSubKey, bool Type);
    //计算并填充子密钥到SubKey数据中
    static void SetSubKey(PSubKey pSubKey, const unsigned char Key[8]);
    static bool RunPad(bool bType, int nType, const unsigned char* In, unsigned datalen,
                        unsigned char* Out, unsigned& padlen);
private:
    enum {
		encrypt = 0,    // 加密
		decrypt,
	};
	enum {
		pad = 0,
	};
	enum {
		ECB = 0,      // ECB模式
		CBC=1,            // CBC模式
	};

};
//初始置换ip,将读入的明文串进行特定顺序重排,之后将前32位和后32位分别记为L0和R0
const 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
};

// 初始置换ip-1,将最终得到的R16,I16进行初始置换的逆置换后得到
const char IPR_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
};

//扩展置换,在计算轮函数时将32位输入扩展位48位,在与子密钥进行安位模2加运算
const char E_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 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 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
};

//置换选择二,将循环左移之后的56位进行置换选择二得到48位,即为密钥Ki
const 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
};

//生成子密钥时,生成Ci/Di时进行循环左移的位数
const char LOOP_Table[16] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 };

//s盒,轮函数里生成s1到s8后再进行P盒置换就成轮函数f(Ri-1,Ki)
const char S_Box[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
};

CDES::CDES() {}
CDES::~CDES() {}
/*加密入口*/


/*十六进制字符串转化为ASCII字符串  每2位十六进制字符 = 8 bit = 1 ASCII字符*/
char * CDES::HexToStr(string s) {
	int temp = 0;
	int len = s.length();
	char * result = new char[len / 2 + 1];

	/*例如十六进制字符串为ACBDC
	ABCD的ascll码分别为:0100 0001
	                     0100 0010
                         0100 0011
                         0100 0100

	  则是(s[i + j] - 'A' + 10)=0000 1010 ,因为这是第一轮,i=0,j=0,所以(4 * (1 - j))=4,需要左移四位,即s[0]=1010 0000
	同理,C转化后为00001100;j第一轮for循环结束,两个16进制数加起来成为一个temp,存放在result[0]中*/
	for (int i = 0; i < len; i += 2) {
		for (int j = 0; j < 2; j++) {
			if (s[i + j] >= '0' && s[i + j] <= '9') {
				temp += (s[i + j] - '0') << (4 * (1 - j));
			}
			else if (s[i + j] >= 'A' && s[i + j] <= 'F') {
				temp += (s[i + j] - 'A' + 10) << (4 * (1 - j));
			}
			else if (s[i + j] >= 'a'&& s[i + j] <= 'f') {
				temp += (s[i + j] - 'a' + 10) << (4 * (1 - j));
			}
		}
		result[i / 2] = (char)temp;
		temp = 0;
	}
	result[len / 2] = '\0';
	return result;
}

/*字符串转化为十六进制  一个字符 = 一个ASCII码 = 两位十六进制数 */
string CDES::StrToHex(char* bytes, int bytelength) {
	string str("");
	string str2("0123456789ABCDEF");

	for (int i = 0; i < bytelength; i++) {
		int b;
		b = 0x0f & (bytes[i] >> 4);
		str.append(1, str2.at(b));
		b = 0x0f & bytes[i];
		str.append(1, str2.at(b));
	}
	return  str;
}

/*
把BYTE转化为Bit流
bits: Bit流的长度[in]
*/
static void ByteToBit(bool *Out, const unsigned char *In, int bits) {
	for (int i = 0; i < bits; ++i)
		Out[i] = (In[i >> 3] >> (7 - i & 7)) & 1;
}

/*
把Bit转化为Byte流
lens: Bit流的长度
*/
static void BitToByte(unsigned char *Out, const bool *In, int lens) {
	memset(Out, 0, lens >> 3);
	for (int i = 0; i < lens; ++i)
		Out[i >> 3] |= In[i] << (7 - i & 7);
}

/*  把BIT流按位向左循环移动
*/
static void zuoyi(bool *In, int len, int loop) {
	bool Tmp[256];
	memcpy(Tmp, In, loop);
	memcpy(In, In + loop, len - loop);
	memcpy(In + len - loop, Tmp, loop);
}

/*
  把两个Bit流进行异或
*/
static void Xor(bool *InA, const bool *InB, int len) {
	for (int i = 0; i < len; ++i)
		InA[i] ^= InB[i];
}

/*
 把两个Bit流按表进行位转化
Table:  转化需要的表指针
*/
static void zhihuan(bool *Out, bool *In, const char *Table, int len) {
	bool Tmp[256];
	for (int i = 0; i < len; ++i)
		Tmp[i] = In[Table[i] - 1];
	memcpy(Out, Tmp, len);
}



//计算子密钥并且填充到pSubKey中
void CDES::SetSubKey(PSubKey pSubKey, const unsigned char Key[8]) {
	bool K[64], *KL = &K[0], *KR = &K[28];
	ByteToBit(K, Key, 64);
	zhihuan(K, K, PC1_Table, 56);

	for (int i = 0; i < 16; ++i) {
		zuoyi(KL, 28, LOOP_Table[i]);
		zuoyi(KR, 28, LOOP_Table[i]);
		zhihuan((*pSubKey)[i], K, PC2_Table, 48);
	}
}


/*
S盒模块
*/
static void Sbox(bool Out[32], const bool In[48]) {
	for (char i = 0, j, k; i < 8; ++i, In+= 6, Out += 4)
	{
		j = (In[0] << 1) + In[5];
		k = (In[1] << 3) + (In[2] << 2) + (In[3] << 1) + In[4];
		for (int l = 0; l < 4; ++l)
			Out[l] = (S_Box[i][j][k] >> (3 - l)) & 1;
	}
}


//轮函数模块


static void lunhs(bool In[32], const bool Ki[48]) {
	bool MR[48];
	zhihuan(MR, In, E_Table, 48);
	Xor(MR, Ki, 48);
	Sbox(In, MR);
	zhihuan(In, In, P_Table, 32);
}

bool CDES::RunDES(bool bType, bool bMode, int PaddingMode, const unsigned char* Iv, const unsigned char* In,
	unsigned char* Out, unsigned datalen, const unsigned char* Key, unsigned keylen)
{
	memset(Out, 0x00, strlen((const char*)Out));
	unsigned char* outbuf = Out;

	/*判断输入合法性*/
	if (!(outbuf && Key && keylen >= 8)) // 空字符串加密的时候In和datalen都为0,应该去掉此判断
		return false;

	unsigned char* inbuf = new unsigned char[datalen + 8]{ 0 };
	memcpy(inbuf, In, datalen);
	unsigned padlen = datalen;

	/* 根据填充模式填充 */
	if (!RunPad(bType, PaddingMode, In, datalen, inbuf, padlen)) {
		delete[]inbuf;
		inbuf = NULL;
		return false;
	}

	unsigned char* tempBuf = inbuf;
	bool m_SubKey[3][16][48];        //密钥

									 /*构造并生成SubKeys */
	unsigned char nKey = (keylen >> 3) >= 3 ? 3 : (keylen >> 3);
	for (int i = 0; i < nKey; i++) {
		SetSubKey(&m_SubKey[i], &Key[i << 3]);
	}

	/*ECB模式*/
	if (bMode == ECB) {
		if (nKey == 1) {
			int j = padlen >> 3;
			for (int i = 0, j = padlen >> 3; i < j; ++i, outbuf += 8, tempBuf += 8)
				DES(outbuf, tempBuf, &m_SubKey[0], bType);
		}

		else if (nKey == 2) {
			for (int i = 0, j = padlen >> 3; i < j; ++i, outbuf += 8, tempBuf += 8) {
				DES(outbuf, tempBuf, &m_SubKey[0], bType);
				DES(outbuf, outbuf, &m_SubKey[1], !bType);
				DES(outbuf, outbuf, &m_SubKey[0], bType);
			}
		}
		else {
			for (int i = 0, j = padlen >> 3; i < j; ++i, outbuf += 8, tempBuf += 8) {
				DES(outbuf, tempBuf, &m_SubKey[bType ? 2 : 0], bType);
				DES(outbuf, outbuf, &m_SubKey[1], !bType);
				DES(outbuf, outbuf, &m_SubKey[bType ? 0 : 2], bType);
			}
		}
	}
	/*CBC模式*/
	else {
		unsigned char   cvec[8] = "";
		unsigned char   cvin[8] = "";

		memcpy(cvec, Iv, 8);

		for (int i = 0, j = padlen >> 3; i < j; ++i, outbuf += 8, tempBuf += 8) {
			if (bType == CDES::encrypt) {
				for (int j = 0; j < 8; ++j)
					cvin[j] = tempBuf[j] ^ cvec[j];
			}
			else {
				memcpy(cvin, tempBuf, 8);
			}

			DES(outbuf, cvin, &m_SubKey[0], bType);
			if (bType == CDES::encrypt) {
				memcpy(cvec, outbuf, 8);
			}
			else {
				for (int j = 0; j < 8; ++j)
					outbuf[j] = outbuf[j] ^ cvec[j];
				memcpy(cvec, cvin, 8);
			}
		}
	}
	if (inbuf) {
		delete[]inbuf;
		inbuf = NULL;
	}

	if (bType == CDES::decrypt) {
		if (PaddingMode == pad) {
			//待补充
		}
	}
	return true;
}


/* DES单元运算 */
void CDES::DES(unsigned char Out[8], const unsigned char In[8], const PSubKey pSubKey, bool Type) {
	bool M[64], tmp[32], *Li = &M[0], *Ri = &M[32];
	ByteToBit(M, In, 64);
	zhihuan(M, M, IP_Table, 64);
	if (Type == encrypt) {
		for (int i = 0; i < 16; ++i) {
			memcpy(tmp, Ri, 32);
			lunhs(Ri, (*pSubKey)[i]);
			Xor(Ri, Li, 32);
			memcpy(Li, tmp, 32);
		}
	}
	else {
		for (int i = 15; i >= 0; --i) {
			memcpy(tmp, Ri, 32);
			lunhs(Ri, (*pSubKey)[i]);
			Xor(Ri, Li, 32);
			memcpy(Li, tmp, 32);
		}
	}
	zuoyi(M, 64, 32);
	zhihuan(M, M, IPR_Table, 64);
	BitToByte(Out, M, 64);
}


bool CDES::RunPad(bool bType, int nType, const unsigned char* In, unsigned datalen, unsigned char* Out, unsigned& padlen) {
	if (nType < pad) //|| nType > pad
		return false;
	if (In == NULL || datalen < 0 || Out == NULL)
		return false;

	int res = (datalen & 0x07); //得到datalen的低三位 也就是对8取余
	if (bType == CDES::decrypt) {
	//	padlen = datalen;
		padlen = datalen / 2;
		memcpy(Out, In, datalen);
		return true;
	}

	memcpy(Out, In, datalen);
	padlen = datalen;
	if (res != 0) {
		padlen += (8 - res);//使成为8的倍数
		if (nType == pad) {
			memset(Out + datalen, 0x00, 8 - res);
		}
	}
	return true;
}


/*加密入口*/
bool CDES::EnCode(string mingwenfile,string miyaofile,string miwenfile) {
	string msg, sKey,IV = "",ivfile;
   int mode;
     cout<<"请输入明文地址:"<<endl;
     cin>>mingwenfile;
	//读入明文并打印
	ifstream msgFile(mingwenfile);
	if (!msgFile.is_open()) {
		cout << "加密时无法打开明文文件!" << endl;
		return false;
	}
	getline(msgFile, msg);
	cout << "明文: " << msg << endl;
	msgFile.close();



	//读入密钥并打印
	 cout<<"请输入密钥地址:"<<endl;
     cin>>miyaofile;
	ifstream keyFile(miyaofile);
	if (!keyFile.is_open()) {
		cout << "加密时无法打开密钥文件!" << endl;
		return false;
	}
	keyFile >> sKey;
	cout << "密钥: " << sKey << endl;
	sKey = HexToStr(sKey);
	keyFile.close();


     cout<<"选择加密模式,ECB模式为0,CBC模式为1"<<endl;
     cin>>mode;
    if (mode == CBC) {
		//读入IV并打印
		cout << "读入IV文件地址:" << endl;
		cin >> ivfile;
		ifstream IVFile(ivfile);
		if (!IVFile.is_open()) {
			cout << "不能打开IV文件!" << endl;
			return false;
		}
		IVFile >> IV;
		cout << "IV: " << IV << endl;
		IV = HexToStr(IV);
		IVFile.close();
	}



	unsigned char buff[1024] = { 0 };

	CDES::RunDES(CDES::encrypt, mode, CDES::pad, (const unsigned char*)IV.c_str(),  (const unsigned char*)msg.c_str(), buff, strlen(msg.c_str()), (const unsigned char*)sKey.c_str(), strlen(sKey.c_str()));
	string restr = StrToHex((char*)buff, strlen((char*)buff));

	cout<<"请输入密文地址:"<<endl;
     cin>>miwenfile;
     cout<<"密文:"<<restr<<endl;
	ofstream cipherFile(miwenfile);
	if (!cin || !cipherFile.is_open())
		return false;
	cipherFile << restr;
	cout <<"加密时写入密文成功!" << endl;
	cipherFile.close();

	return true;
}

/*解密入口*/
bool CDES::DeCode(string miyaofile,string miwenfile,string jmhmingwenfile) {
	string miwen, sKey,IV = "",ivfile;
    int mode;
	//读入密文并打印
	cout<<"请输入密文地址:"<<endl;
     cin>>miwenfile;
	ifstream ciphFile(miwenfile);
	if (!ciphFile.is_open()) {
		cout << "无法打开密文文件!";
		return false;
	}
	ciphFile >> miwen;
	cout << "密文: "<< miwen << endl;
	ciphFile.close();


    cout<<"请输入要读入的密钥文件名:"<<endl;
    cin>>miyaofile;
	ifstream keyFile(miyaofile);

	if (!keyFile.is_open()) {
		cout << "无法打开密钥文件!" << endl;
		return false;
	}
	keyFile >> sKey;
	cout << "密钥: " << sKey << endl;
	sKey = HexToStr(sKey);
	keyFile.close();


     cout<<"选择解密模式,ECB为0,CBC为1:"<<endl;
     cin>>mode;

	if(mode==CBC)
    {
        //读入IV并打印
		cout << "请输入iv文件地址:" << endl;
		cin >> ivfile;
		ifstream IVFile(ivfile);
		if (!IVFile.is_open()) {
			cout << "不能打开iv文件!" << endl;
			return false;
		}
		IVFile >> IV;
		cout << "IV: " << IV << endl;
		IV = HexToStr(IV);
		IVFile.close();

     }

	unsigned char ch[1024] = { 0 };
	char* c = HexToStr(miwen);
	char Out[1024] = { 0 };
	CDES::RunDES(CDES::decrypt, mode, CDES::pad, (const unsigned char*)IV.c_str(), (const unsigned char*)c, (unsigned char*)Out, strlen(miwen.c_str()), (const unsigned char*)sKey.c_str(), strlen(sKey.c_str()));
	string dmingwen = Out;

	cout<<"请输入要读入的解密后明文文件名:"<<endl;
    cin>>jmhmingwenfile;
    cout << "解密后明文: " << dmingwen << endl;
	ofstream decryptedFile(jmhmingwenfile);
	if (!cin || !decryptedFile.is_open())
		return false;
	decryptedFile << dmingwen;
	cout << "解密且保存成功!" << endl;
	decryptedFile.close();

	return true;
}


int main()
{
   CDES cdes;
   string mingwenfile,miyaofile, miwenfile,jmhmingwenfile;
   cout<<"请输入是要进行几加密(仅限于1,2,3)"<<endl;
   int y,x;
   part:
   cin>>y;
   if(y<1||y>3)
   {
     cout<<"错误,请重新输入:"<<endl;
     goto part;
   }
   else{

         if(y==1)
       {
            cout<<"请输入要进行加密还是解密"<<endl;
            cout<<"加密为0,解密为1"<<endl;
            cin>>x;
            if(x==0)
            {
              cdes.EnCode(mingwenfile,miwenfile,miyaofile);
            }
            else if(x==1)
            {
              cdes.DeCode(miwenfile,miyaofile,jmhmingwenfile);
            }

       }
         else if(y==2)
       {
          cout<<"二次加解密未写"<<endl;
          cout<<"请重新输入加密次数:";
          goto part;
       }
         else if(y==3)
      {
            cout<<"请输入要进行加密还是解密"<<endl;
            cout<<"加密为0,解密为1"<<endl;
            cin>>x;
            if(x==0)
            {
            cdes.EnCode(mingwenfile,miwenfile,miyaofile);
            cout<<"第一次加密结束!"<<endl;
            cout<<"第二次加密开始!"<<endl;
            cdes.DeCode(miwenfile,miyaofile,jmhmingwenfile);
            cout<<"第二次加密结束!"<<endl;
            cout<<"第三次加密开始!"<<endl;
            cdes.EnCode(mingwenfile,miwenfile,miyaofile);
            cout<<"第三次加密结束!"<<endl;
            }
            else if(x==1)
            {
            cdes.DeCode(miwenfile,miyaofile,jmhmingwenfile);
            cout<<"第一次解密结束!"<<endl;
            cout<<"第二次解密开始!"<<endl;
            cdes.EnCode(mingwenfile,miwenfile,miyaofile);
            cout<<"第二次解密结束!"<<endl;
            cout<<"第三次解密开始!"<<endl;
            cdes.DeCode(miwenfile,miyaofile,jmhmingwenfile);
            cout<<"第三次解密结束!"<<endl;
            }

        }

   }
   return 0;
}


部分代码学习与csdn,希望大家能相互学习,完善自己。
在这里插入图片描述

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值