1.加密流程
(1)64bit的明文经过一个P盒的初始置换,然后分成左右两个部分
(2)进行十六轮的加密操作,其中上一轮的右部分复制下一轮的左部分,上一轮的右部分经F轮函数操作的结果与该轮左部分进行异或,得出的结果复制给下一轮的右部分。注意,在第16轮时,R16=R15,L16=L15⊕F(R15,K16)
(3)把最后的一轮得出得左右部分结合在一起,在进行一个P盒得置换,得到密文
F轮函数
(1)进入的32bit的右部分,经过扩展P盒的扩展变成48bit
(2)扩展P盒得出的48bit结果与48bit的密钥进行异或
(3)上一步异或的48bit结果在进行8个S盒压缩成32bit
(4)经S盒压缩后的32bit信息再经过一个P盒的置换,得出F轮函数的操作结果
密钥的产生
(1)64bit的密钥信息,经过P盒压缩,变成56bit,并分成左右28bit两个部分
(2)左右了两个部分分别根据每轮移动的值进行循环左移
(3)把循环左移后的两部分密钥重新按左右顺序结合成58bit
(4)58bit的信息在进行一个P盒的压缩变成48bit的该轮密钥K
2.算法框图
3.详详细解释原理参考
DES加密算法_樱木之的博客-CSDN博客_csdn des算法
4.C++代码实现
(1)说明
本算法实现了对一个64bit的十六进制信息的加密,主要是把二进制信息储存在字符串中,通过操作字符串下标来进行替换,异或等操作
(2)所用函数
string BinaryToHex(string binary)//二进制转十六进制,输入二进制的字符串,输出十六进制的字符串
string BinaryToHex(string binary)//二进制转十六进制,输入十六进制的字符串,输出二进制的字符串
string DeciTo4Bin(int n)//十进制转4位二进制,在F轮函数中S盒压缩时用到
string InitialReplace(string binmessage)//初始置换函数,64bit明文的初始置换
string EndInReplace(string binary64)//输出密文前的置换,逆初始置换
string ExtendTrans(string binary32)//扩展变换,F轮函数中的扩展变换
string XOR(string str1, string str2)//两个字符串的异或
string FSboxPress(string binary48)//输出F轮函数中,S盒的压缩,以及压缩后的P盒置换的结果
string KPremuSel1(string keybinary64)//密钥的置换选择1,把64bit的密钥变成54bit
string KeyRoundCreate(string & C0, string& D0, int n)//轮密钥的生成,输入:左28密钥二进制,右28密钥二进制,左移位数。
//输出:48位的二进制密钥,注意C0,D0是引用的传递
void Encryption()//加密函数
(3)代码
#pragma once
#include<iostream>
#include<string>
using namespace std;
/*
//开始
static const int IP[64];//初始时的IP置换盒64bit->32bit+32bit
//最后
static const int IPI[64];//最后输出时的逆初始置换IP:32bit+32bit->64bit
//F论函数
static const int FEP[48];//F轮函数中的EP扩展变换盒,32bit-48bit
static const int FS8[32][16];//F轮函数中的8个S压缩盒;48bit->32bit
static const int FP[32];//F轮函数中的置换运算P盒32bit->32bit
//密钥的产生
static const int CP1[56];//密钥生产过程中的置换选择压缩P1盒64bit->28bit+28bit
static const int CP2[48];//密钥生产过程中的置换选择压缩P2盒28bit+28bit->48bit
static const int CEnRotateLeft[16];//密钥生产过程中每轮的循环左移的数
*/
//初始时的IP置换盒64bit->32bit+32bit
static const int P[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:32bit+32bit->64bit
static const int IPI[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轮函数中的EP扩展变换盒,32bit-48bit
static const int FEP[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 };
//F轮函数中的8个S压缩盒;48bit->32bit
static const int FS8[32][16]= {
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, //S1
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, //S2
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, //S3
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, //S4
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,//S5
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,//S6
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,//S7
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,//S8
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
};
//F轮函数中的置换运算P盒32bit->32bit
static const int FP[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 };
//密钥生产过程中的置换选择压缩P1盒64bit->28bit+28bit
static const int CP1[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 };
//密钥生产过程中的置换选择压缩P2盒28bit+28bit->48bit
static const int CP2[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 };
//密钥生产过程中每轮的循环左移的数
static const int CEnRotateLeft[16]= { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
//各种辅助函数
string HexToBinary(string hex)//十六进制变二进制
{
string binnum = "";
int n = hex.size();
for (int j = 0; j < hex.length(); j++)
{
switch (hex[j])
{
case '0':binnum += "0000"; break;
case '1':binnum += "0001"; break;
case '2':binnum += "0010"; break;
case '3':binnum += "0011"; break;
case '4':binnum += "0100"; break;
case '5':binnum += "0101"; break;
case '6':binnum += "0110"; break;
case '7':binnum += "0111"; break;
case '8':binnum += "1000"; break;
case '9':binnum += "1001"; break;
case 'A':binnum += "1010"; break;
case 'B':binnum += "1011"; break;
case 'C':binnum += "1100"; break;
case 'D':binnum += "1101"; break;
case 'E':binnum += "1110"; break;
case 'F':binnum += "1111"; break;
default:
break;
}
}
return binnum;
}
string BinaryToHex(string binary)//二进制转十六进制
{
string hex = "";
int temp;
for (int i = 0; i < binary.size(); i+=4)
{
//转化为int型
temp = ((int)binary[i]-(int)'0') * 8 + ((int)binary[i+1] - (int)'0') * 4
+ ((int)binary[i+2] - (int)'0') * 2 + ((int)binary[i+3] - (int)'0') * 1;
//cout << temp;
if (temp >= 10)
{
switch (temp)
{
case 10:hex += "A"; break;
case 11:hex += "B"; break;
case 12:hex += "C"; break;
case 13:hex += "D"; break;
case 14:hex += "E"; break;
case 15:hex += "F"; break;
}
}
else
{
hex += to_string(temp);
}
}
return hex;
}
string DeciTo4Bin(int n)//十进制转4位二进制
{
string decimal = "";
while (n)
{
decimal += to_string(n % 2);
n = n / 2;
}
//反转一下
for (int i = 0; i < decimal.size() / 2; i++)
{
char temp;
temp = decimal[i];
decimal[i] = decimal[decimal.size() - 1 - i];
decimal[decimal.size() - 1 - i] = temp;
}
switch (4-decimal.size())
{
case 1:decimal = "0"+ decimal; break;
case 2:decimal = "00" + decimal; break;
case 3:decimal = "000" + decimal; break;
case 4:decimal = "0000" + decimal; break;
default:
break;
}
return decimal;
}
//开始
string InitialReplace(string binmessage)//初始置换函数
{
string binary = "";
for (int i = 0; i < 64; i++)
{
binary += binmessage[P[i] - 1];
}
return binary;
}
//最后
string EndInReplace(string binary64)
{
string out64 = "";
for (int i = 0; i < 64; i++)
{
out64 += binary64[IPI[i] - 1];
}
return out64;
}
//F论函数
string ExtendTrans(string binary32)//扩展变换
{
string out48 = "";
for (int i = 0; i < 48; i++)
{
out48 += binary32[FEP[i] - 1];
}
return out48;
}
string XOR(string str1, string str2)//两个字符串的异或
{
string outcome = "";
for (int i = 0; i < str1.size(); i++)
{
if (str1[i] == str2[i])
outcome += "0";
else
{
outcome += "1";
}
}
return outcome;
}
string FSboxPress(string binary48)
{
int n = 1;//从第一个S盒开始
string binary32 = "";
for (int i = 0; i < binary48.size(); i+=6)
{
int y = ((int)binary48[i] - (int)'0') * 2 + ((int)binary48[i + 5] - (int)'0') * 1;//获取S盒第几行
int x = ((int)binary48[i + 1] - (int)'0') * 8 + ((int)binary48[i + 2] - (int)'0') * 4//获取S盒的第几列
+ ((int)binary48[i + 3] - (int)'0') * 2 + ((int)binary48[i + 4] - (int)'0') * 1;
int tem = FS8[y + (n - 1) * 4][x];//获取该S盒行列位置下的十进制
binary32 += DeciTo4Bin(tem);//把十进制转化位二进制,并复制给要输出的字符串
n++;//调用下一个S盒
}
string premutation = "";
for (int i = 0; i < 32; i++)
{
premutation += binary32[FP[i] - 1];
}
return premutation;
}
//K密钥
string KPremuSel1(string keybinary64)//密钥的置换选择1
{
string out56 = "";
for (int i = 0; i < 56; i++)
{
out56 += keybinary64[CP1[i] - 1];
}
return out56;
}
string KeyRoundCreate(string & C0, string& D0, int n)//轮密钥的生成,输入:左28密钥二进制,右28密钥二进制,左移位数。
//输出:48位的二进制密钥,注意C0,D0是引用的传递
{
string Cnext = "", Dnext = "";//临时储存左移的结果
string out48;//把左移的结果拼接
for (int i = n; i < C0.size(); i++)//对C0循环左移
{
Cnext += C0[i];
Dnext += D0[i];
}
for (int i = 0; i < n; i++)//对D0循环左移
{
Cnext += C0[i];
Dnext += D0[i];
}
//cout << "C0循环左移:" << Cnext << endl;
//cout << "D0循环左移:" << Dnext << endl;
//把传进来的左右两个密钥改为下一轮的新左右两密钥,提供给下一轮使用
C0 = Cnext;
D0 = Dnext;
string temp = Cnext + Dnext;
//拼接的结果,进行置换选择2(压缩P盒)
for (int i = 0; i < 48; i++)
{
out48 += temp[CP2[i] - 1];
}
return out48;
}
//加密
void Encryption()
{
string key = HexToBinary("AABB09182736CCDD");//密钥二进制
string message = HexToBinary("123456ABCD132536");//明文二进制
//密钥
string keypresel1 = KPremuSel1(key);//密钥压缩
string keyleft28 = keypresel1.substr(0, 28);
string keyright28 = keypresel1.substr(28, 28);
string premessage = InitialReplace(message);//初始置换IP,64bit-64bit
//把初始的message分为左右两个部分
string messleft = premessage.substr(0, 32);
string messright = premessage.substr(32, 32);
cout << "轮序0 " << "左:" << BinaryToHex(messleft) << " 右:" << BinaryToHex(messright) << endl;
//获取第一轮密钥
for (int i = 0; i < 16; i++)
{
string kdynextbinary = KeyRoundCreate(keyleft28, keyright28, CEnRotateLeft[i]);//获取轮密钥
string Fextendres = ExtendTrans(messright);//F论函数对右边明文进行扩展,32bit-48bit
string firstxor = XOR(Fextendres, kdynextbinary);//扩展的结果与轮密钥异或
string sboxpress = FSboxPress(firstxor);//异或的结果进行8个S盒的压缩,以及一个P盒的置换
string newright = XOR(messleft, sboxpress);//上步得到的结果在与左边的明文进行异或
if (i < 15)
{
cout << "轮序" << i + 1 << " 左:" << BinaryToHex(messright) << " 右:" << BinaryToHex(newright)
<< " 密钥" << BinaryToHex(kdynextbinary) << endl << endl;
}
else
{
cout << "轮序" << i + 1 << " 左:" << BinaryToHex(newright) << " 右:" << BinaryToHex(messright)
<< " 密钥" << BinaryToHex(kdynextbinary) << endl << endl;
}
//下一轮的新参数;
if (i < 15)
{
messleft = messright;//下一轮的左message
messright = newright;//下一轮的右message
}
else
{
messleft = newright;
}
}
string F16res = messleft + messright;
cout << "左右部分拼接在一起:" << BinaryToHex(F16res) << endl;
string endoutcom = InitialReplace(F16res);
cout << "密文:" << BinaryToHex(endoutcom) << endl;
}