DES加密算原理简述与C++代码实现

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;
}

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

remandancy.h

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值