上應用密碼學,講到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加密算法過程大體可分爲三大部分:
- 輸入64bit明文,進行IP初始置換
- 輸入64bit密鑰,生成16個子密鑰
- 進行16輪迭代變換
- 左右交換後進行逆初始置換( 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函數變換過程如下圖所示
密碼函數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;
}
(全文完)