DES算法的C++实现

上应用密码学,讲到DES算法,要求用C++实现,作为一个初学者,各种找资料,终于搞定了,写篇文章以备后用。本文介绍了 DES 算法加密的大致步骤和整体流程。

 

一、DES算法概述

数据加密标准(Data Encryption Standard,DES)是在美国IBM公司的研究人员Horst Feistel 和Walter Tuchman于20世纪70年代中期提出的一个密码算法(LUCIFER算法(金星算法))的基础之上发展而来的,并于1977年1月15日由美国国家标准局(NBS)正式公布实施,是第一公开的商用密码标准,并得到了ISO的认可。

DES算法是一种典型的Feistel结构的分组密码算法,它的明文分组长度为64bit,密钥长度为64bit,其中密钥有8bit是奇偶校验,因此有效密钥长度为56bit.DES算法的加密和解密采用同一过程,它的安全性依赖于有效密钥。DES算法首先把需要加密的明文划分为每64bit的数据块,用56bit有效密钥对每64bit数据块进行加密。每次加密对输入的64bit的明文数据进行16轮的代替和置换后,输出完全不同于明文的64bit密文。DES算法仅使用最大为64bit的标准算数和逻辑运算,运算速度快,子密钥生产容易,适合于大多数计算机上采用软件方法实现,同时也适合于在专用芯片上实现。

二、DES算法原理

DES算法的加密过程首先对明文分组进行操作,需要加密的明文分为固定大小64bit。

下面是DES加密算法的流程示意图:

DES算法的C++实现_第1张图片

每一个64bit的明文的分组加密处理过程

DES算法的C++实现_第2张图片

DES的16个子密钥的生成过程

从图可以看出,DES加密算法过程大体可分为三大部分:

 

  1. 输入64bit明文,进行IP初始置换
  2. 输入64bit密钥,生成16个子密钥
  3. 进行16轮迭代变换
  4. 左右交换后进行逆初始置换( IP-1 )得到64bit密文

16轮迭代采用Feistel密码结构对明文和密钥进行混淆和扩散

下面以输入明文“computer”和密钥“01234567”为例,分别讲一下各个部分的大致思路。

1)IP初始置换

这部分很简单。初始置换表是一个8x8的矩阵

/*IP初始化置换表*/
	int IP[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
	};

表中的数值是输入的64bit明文块下标1到64。置换过程是输入64bit明文块根据表中下标位置进行置换。即把输入明文块第58位数据放到第一位,50位放到第二位......以此类推,初始置换以后得到的是一个 64 位的输出。

2)子密钥的生成

 

  • 用户将初始密钥64bit输入到子密钥生成器中,首先经过置换选择PC-1,将初始密钥的8bit奇偶校验位去掉,并重新编排,留下真正的56bit有效密钥。
  • 接着,分成两部分,每部分28bit,记为C0和D0,再分别经过一个循环左移函数,每部分循环左移1或2位(每轮次移位位数不同),记为C1和D1,然后再连接成56bit数据C1||D1
  • 再按置换选择PC-2做重排,进行压缩,抛弃8bit后,便可输出第一个48bit子密钥K1,作为函数F的子密钥输入部分。
  • C1、D1各部分继续经循环左移函数,记为C2、D2,继续上述操作,获取下一轮子密钥......一共进行16轮变换,得到16个48位子密钥

这部分需要用到的表 PC-1 和表 PC-2 如下:

/*置换选择PC-1*/
	/*64bit密钥变为56bit*/
	int PC_1[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 
	};
	/*置换选择PC-2*/
	/*56bit密钥压缩成48bit子密钥*/
	int PC_2[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
	};

	/*循环左移位*/
	int shiftBits[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };

3)密码函数F

F函数变换过程如下图所示

DES算法的C++实现_第3张图片

密码函数F(R,k)接受两个输入:32 位的数据和 48 位的子密钥。然后:

 

  • F函数第一个变换为E盒扩展,对输入的某些位进行扩展和置换,将32bit扩展为48bit。
  • 将得到的48bit输出作为输入与对应的48bit子密钥进行异或运算。
  • 将异或之后得到48bit作为S盒输入,分成8组,每组6bit,分别进入8个S盒进行替代压缩,最终输入48bit变为输出32bit。S盒代替是DES算法唯一的非线性变换,是保证DES算法安全性的源泉。DES共有8个固定S盒,一个S盒有16列和4行,每个元素是4bit,通常用十进制表示。S盒的使用方法为:S盒接收到6bit的输入,6bit中的第一个bit和最后一个bit构成2位二进制数为该S盒行号,6bit中间的4bit二进制为该S盒列号,然后根据行号和列号查S盒定义表得到对应的值(一般为十进制数),该值就是S盒变换的输出,并转换为二进制数。
  • 把通过 S 盒置换得到的 8 个 4 位连在一起,形成一个 32 位的数据,作为F函数最后一个变换P盒置换输入。经过P盒置换之后,F函数结束,最后输出32bit的结果数据。

这部分用到了E盒扩展置换表,8个S盒置换表以及P盒置换表,如下:

/*E盒扩展置换*/
	/*将32bit扩展为48bit*/
	int E[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盒代替压缩*/
	/*每个S盒是16x4的置换表*/
	/*48bit压缩为32bit*/
	int S_BOX[8][4][16] = {
		{
			{ 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 }
		},
	{
		{ 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 }
	},
	{
		{ 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 }
	},
	{
		{ 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 }
	},
	{
		{ 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 }
	},
	{
		{ 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 }
	},
	{
		{ 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 }
	},
	{
		{ 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盒置换*/
	/*类似于IP初始化*/
	int P[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
	};

 

4)尾置换IP-1

 

合并 L16 和 R16 得到一个 64 位的数据,再经过尾置换后得到的就是 64 位的密文。注意:要将 L16和 R16 合并成 R16L16(即左右互换)。尾置换表IP-1如下:

/*逆初始化置换表*/
	int IP_1[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 
	};

 

5)bitset类

简单介绍一下要用到的bitset类

 

  • bitset存储二进制数位。
  • bitset就像一个bool类型的数组一样,但是有空间优化——bitset中的一个元素一般只占1 bit,相当于一个char元素所占空间的八分之一。
  • bitset中的每个元素都能单独被访问,例如对于一个叫做foo的bitset,表达式foo[3]访问了它的第4个元素,就像数组一样。
  • bitset有一个特性:整数类型和布尔数组都能转化成bitset。
  • bitset的运算就像一个普通的整数一样,可以进行与(&)、或(|)、异或(^)、左移(<<)、右移(>>)等操作。

通过bitset类可以方便的处理二进制数据。

OK!现在我们可以回到本文的开头,去看看 DES 算法的整体流程图,思路就已经很清楚了。

三、C++实现

/*************************************************************************
> File Name: DES
> Author: baofengxiong
************************************************************************/
#pragma once
#include
#include

using namespace std;
class DES
{
public:
	bitset<32> F(bitset<32> R, bitset<48> k);  //F函数
	bitset<28> leftshift(bitset<28> k, int );  //左移函数
	void generateKeys();                       //生成16个48bit的子密钥
	bitset<64> char_to_bit(const char s[8]);   //将char字符转换为2进制
	bitset<64> change(bitset<64> temp);
	bitset<64> DES_encryp(bitset<64> &plain);  //DES加密 
	bitset<64> DES_decrypt(bitset<64> &cipher);//DES解密
	void get_s(string str) { s = str; }        //获得明文
	void get_key(string key_t) { k = key_t; }  //获得密钥
	void show_encryp(void);
	void show_decrypt(void);
	DES();
	~DES();
private:
	string s;  //明文
	string k;  //密钥
	bitset<64> key;   //64位密钥
	bitset<48> subkey[16];//每一轮子密钥

	/*IP初始化置换表*/
	int IP[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
	};

	/*逆初始化置换表*/
	int IP_1[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 
	};

	/****************密码函数F所用表*******************/
	/*E盒扩展置换*/
	/*将32bit扩展为48bit*/
	int E[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盒代替压缩*/
	/*每个S盒是16x4的置换表*/
	/*48bit压缩为32bit*/
	int S_BOX[8][4][16] = {
		{
			{ 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 }
		},
	{
		{ 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 }
	},
	{
		{ 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 }
	},
	{
		{ 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 }
	},
	{
		{ 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 }
	},
	{
		{ 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 }
	},
	{
		{ 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 }
	},
	{
		{ 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盒置换*/
	/*类似于IP初始化*/
	int P[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
	};
	/******************生成密钥所用表*******************/
	/*置换选择PC-1*/
	/*64bit密钥变为56bit*/
	int PC_1[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 
	};
	/*置换选择PC-2*/
	/*56bit密钥压缩成48bit子密钥*/
	int PC_2[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
	};

	/*循环左移位*/
	int shiftBits[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };



	 
};
#include "DES.h"
#include
#include

using namespace std;

DES::DES()
{
}


DES::~DES()
{
}

bitset<32> DES::F(bitset<32> R, bitset<48> k) {
	//E盒扩展
	bitset<48> expandR;  
	for (int i = 0; i < 48; i++)
		expandR[47 - i] = R[32 - E[i]];  //expandR[i] = R[E[i] - 1];
	//异或
	expandR = expandR ^ k;
	//S盒代替
	bitset<32> output;
	int x = 0;
	for (int i = 0; i < 48; i = i + 6)
	{
		int row = expandR[i] * 2 + expandR[i + 5];
		int col = expandR[i + 1] * 8 + expandR[i + 2] * 4 + expandR[i + 3] * 2 + expandR[i + 4];
		int num = S_BOX[i / 6][row][col];
		bitset<4> temp(num);
		output[x + 3] = temp[0];
		output[x + 2] = temp[1];
		output[x + 1] = temp[2];
		output[x] = temp[3];
		x += 4;
	}
	//P盒置换
	bitset<32> tmp = output;
	for (int i = 0; i < 32; i++)
		output[i] = tmp[P[i] - 1];

	return output;
}
//左移函数
bitset<28> DES::leftshift(bitset<28> k, int shift) {
	bitset<28> temp = k;
	if (shift == 1)
	{
		for (int i = 0; i < 27; i++)
		{
			if (i - shift < 0)
				k[i - shift + 28] = temp[i];
			else
				k[i] = temp[i + shift];
		}
	}
	if (shift == 2)
	{
		for (int i = 0; i < 26; i++)
		{
			if (i - shift < 0)
				k[i - shift + 28] = temp[i];
			else
				k[i] = temp[i + shift];
		}
	}
	return k;
}

void DES::generateKeys() {
	bitset<56> real_key;
	bitset<28> left;
	bitset<28> right;
	bitset<48> compressKey;

	//首先经过选择置换PC-1,将初始密钥的8bit奇偶校验位去掉
	//并重新编排
	for (int i = 0; i < 56; i++)
		real_key[i] = key[PC_1[i] - 1];

	for (int round = 0; round < 16; round++)
	{
		for (int i = 0; i < 28; i++)
			left[i] = real_key[i];
		for (int i = 28; i < 56; i++)
			right[i - 28] = real_key[i];
		//左移
		left = leftshift(left, shiftBits[round]);
		right = leftshift(right, shiftBits[round]);
		//连接,置换选择PC-2做重排,进行压缩
		for (int i=0; i < 28; i++)
			real_key[i] = left[i];
		for (int i = 28; i < 56; i++)
			real_key[i] = right[i - 28];
		for (int i = 0; i < 48; i++)
		{
			int m = PC_2[i];
			compressKey[i] = real_key[m - 1];
		}                                   
		
		subkey[round] = compressKey;
	}

}


// 工具函数:将char字符数组转为二进制
bitset<64> DES::char_to_bit(const char s[8]) {
	bitset<64> bits;
	int x = 0;
	for (int i = 0; i < 8; i++)
	{
		int num = int(s[i]);
		bitset<8> temp(num);
		for (int j = 7; j >= 0; j--)
		{
			bits[x + j] = temp[7 - j];
		}
		x += 8;
	}
	/*for (int i = 0; i<8; ++i)
		for (int j = 0; j<8; ++j)
			bits[i * 8 + j] = ((s[i] >> j) & 1);
			*/
	return bits;
}
//工具函数:进行二进制逆向转换
bitset<64> DES::change(bitset<64> temp) {
	bitset<64> bits;
	bitset<8> n;
	for (int i = 0; i < 64; i = i + 8)
	{
		for (int j = 0; j < 8; j++)
		{
			bits[i + j] = temp[i + 7 - j];
		}
	}
	return bits;
}

bitset<64> DES::DES_encryp(bitset<64> &plain) {
	bitset<64> cipher;
	bitset<64> currentBits;
	bitset<32> left;
	bitset<32> right;
	bitset<32> newLeft;
	//初始置换IP
	for (int i = 0; i < 64; i++)
		currentBits[i] = plain[IP[i] - 1];//

	for (int i = 0; i < 32; i++)
		left[i] = currentBits[i];
	for (int i = 32; i < 64; i++)
		right[i - 32] = currentBits[i];
	//进入16轮轮变换
	for (int round = 0; round < 16; round++)
	{
		newLeft = right;
		right = left ^ F(right, subkey[round]);
		left = newLeft;
	}
	//合并
	for (int i = 0; i < 32; i++)
		cipher[i] = right[i];
	for (int i = 32; i < 64; i++)
		cipher[i] = left[i - 32];
	//逆初始化置换
	currentBits = cipher;
	for (int i = 0; i < 64; i++)
		cipher[i] = currentBits[IP_1[i] - 1];

	return cipher;
}

bitset<64> DES::DES_decrypt(bitset<64> & cipher) {
	bitset<64> plain;
	bitset<64> currentBits;
	bitset<32> left;
	bitset<32> right;
	bitset<32> newLeft;
	//置换IP
	for (int i = 0; i < 64; i++)
		currentBits[i] = cipher[IP[i] - 1];

	for (int i = 0; i < 32; i++)
		left[i] = currentBits[i];
	for (int i = 32; i < 64; i++)
		right[i - 32] = currentBits[i];
	//进入16轮迭代(子密钥逆序应用)
	for (int round = 0; round < 16; round++)
	{
		newLeft = right;
		right = left ^ F(right, subkey[15 - round]);
		left = newLeft;
	}
	//合并
	for (int i = 0; i < 32; i++)
		plain[i] = right[i];
	for (int i = 32; i < 64; i++)
		plain[i] = left[i - 32];
	//逆初始化置换
	currentBits = plain;
	for (int i = 0; i < 64; i++)
		plain[i] = currentBits[IP_1[i] - 1];

	return plain;
}


void DES::show_encryp() {
	bitset<64> plain = char_to_bit(s.c_str());
	key = char_to_bit(k.c_str());
	// 生成16个子密钥
	generateKeys();
	// 密文写入 a.txt
	bitset<64> cipher = DES_encryp(plain);
	fstream file1;
	file1.open("D://a.txt", ios::binary | ios::out);
	file1.write((char*)&cipher, sizeof(cipher));
	file1.close();
}

void DES::show_decrypt() {
	// 读文件 a.txt
	bitset<64> temp;
	fstream file2;
	file2.open("D://a.txt", ios::binary | ios::in);
	file2.read((char*)&temp, sizeof(temp));
	file2.close();

	// 解密,并写入文件 b.txt
	bitset<64> temp_plain = DES_decrypt(temp);
	bitset<64> temp_1 = change(temp_plain);

	file2.open("D://b.txt", ios::binary | ios::out);
	file2.write((char*)&temp_1, sizeof(temp_1));
	file2.close();
}

DES是典型的Feistel密码结构,因此解密过程与加密过程完全一样,只是输入不一样。注意子密钥逆序输入。

#include
#include
#include
#include"DES.h"

using namespace std;
int main() {
	DES C;
	string s = "computer";
	string k = "01234567";
	C.get_s(s);
	C.get_key(k);
	cout << "Start encryo..." << endl;
	clock_t start = clock();
	C.show_encryp();  //加密,生成密文并写入a.txt
	clock_t finish = clock();
	cout << "finish" << endl;
	cout << "using " << (double)(finish - start) / CLOCKS_PER_SEC << "s." << endl;
	cout << "\n";
	cout << "start decrypt..." << endl;
	start = clock();
	C.show_decrypt(); //读取a.txt中的密文,解密,生成明文并写入b.txt
	finish = clock();
	cout << "finish" << endl;
	cout << "using " << (double)(finish - start) / CLOCKS_PER_SEC << "s." << endl;

	cin.get();
	return 0;
}

源代码下载

https://download.csdn.net/download/weixin_42023723/11168167

(全文完)

你可能感兴趣的:(安全)