代码拉取完成,页面将自动刷新
//blog:https://blog.csdn.net/weixin_43409257/article/details/105924218
//todo:示范代码的加密部分还没看;以及解密部分还没写
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstring>
using namespace std;
const static unsigned char IP_Table[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表
const static unsigned char IPR_Table[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
};//初始逆置换IP表
const static unsigned char PC1_Table[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
};//先将输入的56比特秘钥按上表置换,然后将置换结果分为左右各为28位的C和D
const static unsigned char PC2_Table[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
};//将循环移位后的结果输入,将56比特密钥压缩成48比特,成为本轮的子密钥
const static unsigned char LOOP_Table[16] = {
1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};//左循环移位位数表
const static unsigned char E_Table[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
};//扩展置换E盒(32位扩展至48位)
const static unsigned char P_Table[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
};//置换运算P盒(产生雪崩效应)
const static unsigned char S_Box[8][4][16] = {
// S1
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,
// S2
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,
// S3
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,
// S4
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,
// S5
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,
// S6
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,
// S7
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,
// S8
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
};
class DES
{
public:
DES();
~DES();
void GetKey();
void Encryption();
void print( int ,bool *,const char *,int);
private:
int buffer[8];//输入的值临时存放的地方
bool PlainText_binary[64];//明文最后实际存的地方
bool SubKey[16][48];//子密钥
};
DES::DES()
{
}
DES::~DES()
{
}
void DES::print(int column,bool *arr,const char *str,int times=0) {
if (times>=1)
{
return;
}
if (times == 0) {
cout << str <<":"<< endl;//解释文本
}
else
{
cout << str <<times<<':'<< endl;//解释文本
}
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < column; j++) {
cout << arr[i * column + j];
}
cout << ' ';
}
cout << endl;
}
void DES::GetKey() {
//-----------------------------------------------------------------获取用户输入的密钥---------------------------------------------------
bool Key_binary[64];//密钥最后实际存的地方
cout << "请输入16位16进制的密钥" << endl;
scanf("%2x%2x%2x%2x%2x%2x%2x%2x", &buffer[0], &buffer[1], &buffer[2], &buffer[3], &buffer[4], &buffer[5], &buffer[6], &buffer[7]);
//用2控制输入的宽度,用x告诉系统输入的是16进制
unsigned char Key[8];//临时存放密钥
for (int i = 0; i < 8; i++)
{
Key[i] = buffer[i];
}//按8位来存储,为后面位操作做准备
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++) {
Key_binary[i * 8 + j] = Key[i] & 0x80;//0x不要忘记了
Key[i] = Key[i] << 1;
}
}//通过位操作来得到输入的每一个数
//打印输出密钥
print( 8, Key_binary, "密钥");
//------------------------------------------------------------置换选择1(PC-1)---------------------------------------------------------------
bool Pc1Result[56];//置换选择1(PC-1)的结果
for (int i = 0; i < 56; i++)
{
Pc1Result[i] = Key_binary[PC1_Table[i] - 1];
}
//打印输出置换选择1(PC-1)的结果
print(7, Pc1Result, "置换选择1(PC-1)的结果");
//----------------------------------------------------------将密钥分成两份-------------------------------------------------------------
bool C0[28], D0[28];
for (int i = 0; i < 28; i++)
{
C0[i] = Pc1Result[i];
D0[i] = Pc1Result[i + 28];//通过+28就将原来要写判断或者两个循环轻松解决了,太巧妙了
}
//------------------------------------------------------------循环生成密钥---------------------------------------------------------------
for (int t = 0; t < 16; t++)
{
//------------------------------------------循环左移
bool C1[28], D1[28];
for (int i = 0; i < 28; i++)
{
C1[i] = C0[(i + LOOP_Table[t]) % 28];
D1[i] = D0[(i + LOOP_Table[t]) % 28];
}
//------------------------------------------置换选择2
bool C1_And_D1[56];//C1和D1连接起来
for (int i = 0; i < 28; i++)
{
C1_And_D1[i] = C1[i];
C1_And_D1[i + 28] = D1[i];
}
//打印输出循环左移的结果
print( 7, C1_And_D1, "C和D分别循环左移结果",t);
bool Pc2Result[48];//置换选择2的结果
for (int i = 0; i < 48; i++)
{
Pc2Result[i] = C1_And_D1[PC2_Table[i] - 1];
}
//打印输出置换选择2的结果
print(6, Pc2Result, "子密钥(置换选择2结果)k", t);
//保存子密钥
memcpy(SubKey[t], Pc2Result, 48);
//保存本轮循环移位结果供下轮使用
memcpy(C0, C1, 28);
memcpy(D0, D1, 28);
}
}
void DES::Encryption() {
//-----------------------------------------------------------------获取用户输入的明文---------------------------------------------------
cout << "请输入16位16进制的明文" << endl;
scanf("%2x%2x%2x%2x%2x%2x%2x%2x", &buffer[0], &buffer[1], &buffer[2], &buffer[3], &buffer[4], &buffer[5], &buffer[6], &buffer[7]);
//用2控制输入的宽度,用x告诉系统输入的是16进制
unsigned char PlainText[8];//临时存放明文
for (int i = 0; i < 8; i++)
{
PlainText[i] = buffer[i];
}//按8位来存储,为后面位操作做准备
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++) {
PlainText_binary[i * 8 + j] = PlainText[i] & 0x80;//0x不要忘记了
PlainText[i] = PlainText[i] << 1;
}
}//通过位操作来得到输入的每一个数
//打印输出明文
print( 8, PlainText_binary, "明文二进制");
//------------------------------------------------------------初始置换IP----------------------------------------------------------------
bool IpResult[64];//初始置换IP的结果
for (int i = 0; i < 64; i++)
{
IpResult[i] = PlainText_binary[IP_Table[i] - 1];
}
//打印输出初始置换后的结果
print( 8, IpResult, "初始置换结果:");
//------------------------------------------------------------分成左右两部分----------------------------------------------------------------
bool L0[32], R0[32];
for (int i = 0; i < 32; i++)
{
L0[i] = IpResult[i];
R0[i] = IpResult[i + 32];
}
//------------------------------------------------------------迭代----------------------------------------------------------------
for (int t = 0; t < 16; t++)
{
//------------------------------------------------------------扩展置换E
bool EResult[48];//扩展置换E盒的结果
for (int i = 0; i < 48; i++)
{
EResult[i] = R0[E_Table[i] - 1];
}
//打印输出扩展置换E盒的结果
print(6, EResult, "扩展置换E盒的结果",t);
//-----------------------------------------------------------E盒结果和子密钥异或
bool R0_XOR[48];//E盒结果和子密钥异或的结果
for (int i = 0; i < 48; i++)
{
R0_XOR[i] = SubKey[t][i] ^ EResult[i];
}
//打印输出E盒结果和子密钥异或的结果
print(6, R0_XOR, "E盒结果和子密钥异或的结果",t);
//-----------------------------------------------------------S盒代换
unsigned char buffer;
bool Sresult[32];
for (int i = 0; i < 48; i = i + 6)
{
//bool类型竟然也可以乘与2
buffer = S_Box[i / 6][R0_XOR[i] * 2 + R0_XOR[i + 5]][R0_XOR[i + 1] * 8 + R0_XOR[i + 2] * 4 + R0_XOR[i + 3] * 2 + R0_XOR[i + 4]];
//i/6代表第几轮
for (int k = 0; k < 4; k++)//因为sresult恰好是bool类型歪打正着,日后最好重构代码,可以和0x01与,然后倒序赋值
{
Sresult[(i / 6) * 4 + k] = buffer & 0x08;//0000 1000,得到S盒结果的第一位
buffer = buffer << 1;
}
}
//打印输出S盒代换结果
print( 4, Sresult, "S盒代换结果",t);
//-----------------------------------------------------------P盒置换
bool Presult[32];//P置换结果
for (int i = 0; i < 32; i++)
{
Presult[i] = Sresult[P_Table[i] - 1];
}
//打印输出P置换结果
print( 4, Presult, "P置换结果",t);
//-----------------------------------------------------------P置换结果和L0异或
bool R1[32];//P置换结果和L0异或的结果
for (int i = 0; i < 32; i++)
{
R1[i] = Presult[i] ^ L0[i];
}
//打印输出R1
print( 4, R1, "R1结果",t);
print( 4, R0, "L1结果",t);
//保存结果供下一轮使用
memcpy(L0, R0, 32);
memcpy(R0, R1, 32);
}
//------------------------------------------------------------连接L和R----------------------------------------------------------------
unsigned char L_And_R[64];
for (int i = 0; i < 32; i++)//由于第16轮R和L交换了,而DES最后一轮不用交换,所以连接的时候把R放在前面即可
{
L_And_R[i] = R0[i];
L_And_R[i+32] = L0[i];
}
//------------------------------------------------------------逆初始置换----------------------------------------------------------------
bool IprResult[64];//逆初始置换IP的结果
for (int i = 0; i < 64; i++)
{
IprResult[i] = L_And_R[IPR_Table[i] - 1];
}
//打印输出逆初始置换后的结果
print( 8, IprResult, "逆初始置换结果:");
//------------------------------------------------------------转化成16进制----------------------------------------------------------------
cout << "加密结果:" << endl;
int result[16];
for (int i = 0; i < 16; i++)
{
buffer[i] = IprResult[i * 4 ] * 8 + IprResult[i * 4 +1] * 4 + IprResult[i *4 +2] * 2 + IprResult[i * 4 +3];
cout << hex << buffer[i];
}//一次只可算4位,一次算8位的话,会导致0A只输出0
}
int main()
{
DES des;
des.GetKey();
des.Encryption();
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。