📄 ebc des.cpp
字号:
/*
*************************************************************************************
*数据结构课程设计:DES的实现
*哈尔滨工业大学
*05级计算机学院信息安全专业
*作者:吴世山
*学号:1050320103
*程序作用:实现DES加密、解密、文件加密的EBC算法和位操作
*版本号:1.02
*说明:此程序为DES加密程序
*日期:2007年11月11日
*************************************************************************************
*/
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define max 100
unsigned char pd[32]; //口令
unsigned char mw[8]; //明文/密文
unsigned char m[64]; //二进制明文/密文
unsigned char bkey[8]; //char型密钥
unsigned char key[64]; //二进制密钥
unsigned char ER[48]; //由32位扩展后的右48位
unsigned char dmw[8]={0}; //编码后的明文/密文
unsigned char zkey[56]; //临时存储密钥
unsigned char dkey[16][56]; //16个子密钥
FILE* fptr=NULL, *dfptr;
double size; //文件大小
unsigned char* L, *R;
static unsigned char ip[64]={ //初始置换IP
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
};
static unsigned char ip1[64]={ //初始置换IP的逆IP-1
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
};
static unsigned char pc1[56]={ //密钥置换1
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
};
static unsigned char pc2[48]={ //密钥置换2
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 unsigned char e[48]={ //扩充置换E
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
};
static unsigned char lcircle[16]={ //每一轮要循环的次数
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
static unsigned char s[8][4][16]={ //S表
// 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
};
static unsigned char P[32]={ //置换P
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
};
void password(unsigned char* pd, unsigned char* bkey); //口令处理
void encode(); //加密
void decode(); //解密
void getbit(unsigned char* m, unsigned char* mw); //char转二进制
void replace(unsigned char* a, unsigned char* b, int n);//置换函数
void circle(unsigned char* key, int n); //左移位函数
void XOR(unsigned char* a, unsigned char* b, int n); //异或函数
void S_box(unsigned char* a); //S盒
void getchars(unsigned char* a, unsigned char* mw); //二进制转char
int add(unsigned char* a); //求和函数
void getdkey(unsigned char* key); //产生16个子密钥
void enrepeat(); //加密循环
void derepeat(); //解密循环
void getbmphead(FILE* fptr, FILE* dfptr); //读出BMP文件头
int main()
{
int i, n;
char filename[256], c;
printf("***************DES加密EBC模式***************\n");
printf("请输入要加密的文件:\n");
gets(filename);
fptr=fopen(filename, "rb");
if(fptr==NULL)
{
printf("文件不能打开或文件不存在!\n");
return 0;
}
fseek(fptr,0,SEEK_END);//得到文件大小/字节数
size=ftell(fptr);
rewind(fptr);
dfptr=fopen("encryption.bmp", "wb+");
printf("请输入密码:");
i=0;
pd[i]=getchar();
while(pd[i]!='\n')
{
i++;
pd[i]=getchar();
}
if(pd[0]=='\n')
{
printf("密码不合法!\n");
return 0;
}
password(pd, bkey);
getbit(key, bkey); //将密钥转换为二进制
replace(key, pc1, n=56); //key置换成56位
getdkey(key); //得到16个子密钥
printf("加密中......\n");
getbmphead(fptr, dfptr);
encode(); //加密
fclose(fptr);
fclose(dfptr);
printf("加密完成!\n");
printf("是否使用解密程序?(y/n)");//由于解密程序不完善,暂不建议使用
c=getchar();
if(c=='y')
{
printf("解密中......\n");
fptr=fopen("encryption.bmp", "rb");
dfptr=fopen("decryption.bmp", "wb+");
getbmphead(fptr, dfptr);
decode(); //解密
fclose(fptr);
fclose(dfptr);
printf("解密完成!\n");
}
else
return 0;
return 0;
}
void password(unsigned char* pd, unsigned char* bkey)//根据口令产生64位密钥,大于64位截取,小于补齐
{
int i, j=0;
for(i=0;i<8;i++)
{
if(pd[j]=='\n')
{
j=0;
i--;
}
else
{
bkey[i]=pd[j];
j++;
}
}
return ;
}
void encode()
{
int n;
while(ftell(fptr)<size)
{
fread(&mw[0], 1, 8, fptr);
getbit(m, mw); //将明文转换为二进制
replace(m, ip, n=64); //明文的初始置换
L=&m[0]; //明文分为左右两部分
R=&m[32];
enrepeat();
replace(L, ip1, 64); //逆初始置换
getchars(L, dmw);
fwrite(&dmw[0], 1, 8, dfptr);
}
return;
}
void decode()
{
int n, s=0;
while((s=ftell(fptr))<size)
{
fread(&mw[0], 1, 8, fptr);
getbit(m, mw); //将密文转换为二进制
L=&m[0]; //密文分为左右两部分
R=&m[32];
replace(m, ip, n=64); //密文的初始置换
derepeat();
replace(L, ip1, 64); //逆初始置换
getchars(L, dmw);
fwrite(&dmw[0], 1, 8, dfptr);
}
return;
}
void derepeat()
{
int i, n, q, j=0;
for(q=0;q<16;q++) //************进入16轮迭代******************
{
for(i=0;i<56;i++)
zkey[i]=dkey[15-q][i];
replace(zkey, pc2, n=48); //密钥紧缩成48位
for(i=0;i<32;i++)
ER[i]=R[i];
replace(ER, e, n=48); //对右半部分进行扩充,到48位
///////////////////////////////////////////////////////////////////////////////////
XOR(ER, zkey, n=48); //右半部分与密钥(48位)进行异或
S_box(ER); //进入S盒操作
replace(ER, P, n=32); //对右半部分进行P置换
////////////////////////////////////////////////////////////////////////////////////
XOR(ER, L, n=32); //左右异或
for(i=0;i<32;i++) //左右交换
{
L[i]=R[i];
R[i]=ER[i];
}
if(q==15) //16次完毕再交换一次
{
for(i=0;i<32;i++)
{
ER[i]=R[i];
R[i]=L[i];
L[i]=ER[i];
}
}
}
}
void enrepeat()
{
int i, n, q;
for(q=0;q<16;q++) //************进入16轮迭代******************
{
for(i=0;i<56;i++)
zkey[i]=dkey[q][i];
replace(zkey, pc2, n=48);//密钥紧缩成48位
for(i=0;i<32;i++)
ER[i]=R[i];
replace(ER, e, n=48); //对右半部分进行扩充,到48位
///////////////////////////////////////////////////////////////////////////////////
XOR(ER, zkey, n=48); //右半部分与密钥(48位)进行异或
S_box(ER);//进入S盒操作
replace(ER, P, n=32); //对右半部分进行P置换
////////////////////////////////////////////////////////////////////////////////////
XOR(ER, L, n=32); //左右异或
for(i=0;i<32;i++) //左右交换
{
L[i]=R[i];
R[i]=ER[i];
}
if(q==15) //16次完毕再交换一次
{
for(i=0;i<32;i++)
{
ER[i]=R[i];
R[i]=L[i];
L[i]=ER[i];
}
}
}
}
void getdkey(unsigned char* key)
{
int i, j;
for(i=0;i<16;i++)
{
circle(key, i);
for(j=0;j<56;j++)
{
dkey[i][j]=key[j]; //得到16个子密钥
}
}
return;
}
void getbit(unsigned char* m, unsigned char* mw)
{
int i, j;
unsigned char and[8]={128, 64, 32, 16, 8, 4, 2, 1};
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
if((mw[i]&and[j])==0) //用与的方法取出对应的二进制位
m[i*8+j]=0;
else
m[i*8+j]=1;
}
}
return;
}
void replace(unsigned char* a, unsigned char* b, int n)
{
int i;
unsigned char c[max]; //进行置换
for(i=0;i<n;i++)
c[i]=a[b[i]-1];
for(i=0;i<n;i++)
a[i]=c[i];
return;
}
void circle(unsigned char* key, int n)
{
int i, j, k;
switch(lcircle[n]) //密钥左循环:前28位循环左移,后28位循环左移
{
case 1:
j=key[0];
for(i=0;i<27;i++)
key[i]=key[i+1];
key[27]=j;
j=key[28];
for(i=28;i<55;i++)
key[i]=key[i+1];
key[55]=j;
break;
case 2:
j=key[0];
k=key[1];
for(i=0;i<26;i++)
key[i]=key[i+2];
key[26]=j;
key[27]=k;
j=key[28];
k=key[29];
for(i=28;i<54;i++)
key[i]=key[i+2];
key[54]=j;
key[55]=k;
break;
}
return;
}
void XOR(unsigned char* a, unsigned char* b, int n)
{
int i;
for(i=0;i<n;i++)
a[i]=a[i]^b[i];
return;
}
void S_box(unsigned char* a)
{
int i, j;
unsigned char b[8][6];
unsigned char c[8];
for(i=0;i<8;i++) //将48位分为8组,每组六位
{
for(j=0;j<6;j++)
b[i][j]=a[i*6+j];
}
for(i=0;i<8;i++)
{
c[i]=s[i] [ b[i][0]*2+b[i][5] ] [ b[i][1]*8+b[i][2]*4+b[i][3]*2+b[i][4] ];//找到S表中对应的十进制数
}
for(i=0;i<8;i++) //将十进制转换成二进制
{
for(j=3;j>=0;j--)
{
a[i*4+j]=c[i]%2;
c[i]/=2;
}
}
return;
}
void getchars(unsigned char* a, unsigned char* dmw)
{
int i;
for(i=0;i<8;i++)
dmw[i]=add(&a[i*8]); //二进制转换成十进制char
return;
}
int add(unsigned char* a)
{
return a[0]*128+a[1]*64+a[2]*32+a[3]*16+a[4]*8+a[5]*4+a[6]*2+a[7];
}
void getbmphead(FILE* fptr, FILE* dfptr)
{
int i;
char c;
for(i=0;i<54;i++)
{
c=fgetc(fptr);
fputc(c, dfptr);
}
return ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -