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加密算法的流程示意圖:

每一個64bit的明文的分組加密處理過程

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函數變換過程如下圖所示

300

密碼函數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<bitset>
#include<string>

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<bitset>
#include<fstream>

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<iostream>
#include<string>
#include<ctime>
#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;
}

 

(全文完)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章