#include<iostream>
#include<stdio.h>
#include <stdlib.h>
#include <string>
#include <math.h>
#include<windows.h>
using namespace std;
static int PC1_Table[56]={
//Co
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,
//Do
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
};
//初始逆置换IP^-1
const static int 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
};
//16个子密钥
static char subKey[16][49];
//初始置换IP
const static int 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
};
//置换选择2(PC-2)
const static int 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
};
//轮左移表
static int LeftShiftTable[16]={
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
//S盒
const static int 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
};
//置换P
const static int 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
};
//选择扩展运算E
static const 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
};
//逆序排列
void Reverse(char *arr, int begin, int end)
{
char temp;
for(;begin < end; begin++, end--)
{
temp =arr[begin];
arr[begin] = arr[end];
arr[end] = temp;
}
}
//循环左移n位
void LeftShift(char *arr, int n)
{
Reverse(arr, 0, n); //逆序前n位
Reverse(arr, n, 28-1); //逆序后所有位
Reverse(arr, 0, 28-1); //逆序所有位
}
//char转为二进制
char *CharToBi(char *M)
{
char *a = new char[65];
a[64] = '\0';
for(int i = 0; i<8; i++)
{
int m = (int)M[i];
for(int j = 0; j<8; j++)
{
a[i*8+7-j] = m%2+48;
m = m/2;
}
}
return a;
}
//置换选择1
char *RPC_1(char *BiKey)
{
char * realKey = new char[57]; realKey[56] = '\0';
for(int i = 0; i < 56; i++)
{
int index = PC1_Table[i] - 1;
realKey[i] = BiKey[index];
}
//cout<<realKey<<endl;
return realKey;
}
//初始置换IP
void InitIP(char *BiMsg)
{
char * BiMsgCopy = new char [65]; BiMsgCopy[64] = '\0';
memcpy(BiMsgCopy, BiMsg, 65*sizeof(char));
for(int i = 0; i < 64; i++)
{
int index = IP_Table[i]-1;
BiMsg[i] = BiMsgCopy[index];
}
delete[] BiMsgCopy;
}
//64位密钥产生16个48位子密钥
void generateSubKey(char *Bikey, char subKey[16][49])
{
char * realKey = new char[57]; realKey[56] = '\0';
realKey = RPC_1(Bikey);
//C和D
char *C = new char[29]; C[28] = '\0';
char *D = new char[29]; C[28] = '\0';
for(int i = 0; i < 28; i++)
{
C[i] = realKey[i];
D[i] = realKey[i+28];
}
for(int k = 0; k < 16; k++)
{
//左移
LeftShift(C, LeftShiftTable[k]);
LeftShift(D, LeftShiftTable[k]);
//组合C和D
char *CDCombine = new char[57]; CDCombine[56] = '\0';
for(int i = 0; i < 28; i++)
{
CDCombine[i] = C[i];
CDCombine[i+28] = D[i];
}
//密钥选择算法2(PC-2)
for( i = 0; i < 48; i++)
{
int index = PC2_Table[i];
subKey[k][i] = CDCombine[index];
}
subKey[k][48] = '\0';
}
}
//初始逆置换
//DES加密算法
//输入:64位2进制明文,64位2进制密钥,加密解密方式(mode=0表示加密,mode=1表示解密)
//输出:加密后密文或者解密后明文
char *DES(char * BiMsg, char * BiKey, int mode)
{
//对明文进行初始置换IP
InitIP(BiMsg);
//产生16个子密钥
generateSubKey(BiKey, subKey);
//将乱序明文分成Lo和Ro
char *L = new char [33];
char *R = new char [33];
for(int i = 0; i < 32; i++)
{
L[i] = BiMsg[i];
R[i] = BiMsg[i + 32];
}
//16轮迭代
for(int k = 0; k < 16; k++)
{
char *RCopy = new char[33];
memcpy(RCopy, R, 33);
//扩展置换E
char * ExtendedR = new char[49]; ExtendedR[49] = '\0';
for(int i = 0; i < 48; i++)
{
int index = E_Table[i] - 1;
ExtendedR[i] = R[index];
}
//异或
for( i = 0; i < 48; i++)
{
char * temp = new char[65];
if(mode == 0)
{//加密
memcpy(temp, subKey[k], 48);
}
else if(mode == 1)
{
memcpy(temp, subKey[15-k], 48);
}
if(ExtendedR[i] == temp[i])
{
ExtendedR[i] = '0';
}
else
{
ExtendedR[i] = '1';
}
}
//S盒变换
int indexR = 0;
for(int s = 0; s < 8; s++)
{
//将48比特数据从左至右分成8组
char group[7]; group[6] = '\0';
for(int i = 0; i < 6; i++)
{
group[i] = ExtendedR[s*6 +i];
}
//确定S盒的行列
int x, y;
x = group[0]*1 + group[5]*2;
y = group[1]*1 + group[2]*2 + group[3]*4 + group[4]*8;
int target = S_Box[s][x][y];
char *biTarget = new char[5]; biTarget[4] = '\0';
for( i =0; i < 4; i++)
{
biTarget[3-i] = target%2 + 48;
target = target/2;
}
for( i = 0; i < 4; i++)
{
R[indexR] = biTarget[i];
indexR++;
}
}
//P置换
char *SR = new char[33];
memcpy(SR, R, 33);
for(i = 0; i < 32; i++)
{
int index = P_Table[i] - 1;
R[i] = SR[index];
}
//与L进行异或
for(i = 0; i < 32; i++)
{
if(R[i] == L[i])
{
R[i] = '0';
}
else
{
R[i] = '1';
}
}
//L(i) = R(i - 1)
memcpy(L, RCopy, 33);
}
//32位互换
char *RLChange = new char[65];
for(i = 0; i < 32; i++)