⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cbc des.cpp

📁 这是一个密码学实验的程序,主要是根据CBC和DES算法进行加密数据
💻 CPP
字号:
/*
*************************************************************************************
*数据结构课程设计:DES的实现
*哈尔滨工业大学
*05级计算机学院信息安全专业
*作者:吴世山 
*学号:1050320103
*程序作用:实现DES加密、解密、文件加密的CBC(密码分组连接)算法和位操作
*版本号:1.03 
*说明:此程序为DES加、解密程序
*日期:2007年11月11日
*************************************************************************************
*/


#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define max 100


unsigned char pd[32];        //password
unsigned char random_key[64];//随机序列用于CBC加密
unsigned char r_key[64];     //随机序列
unsigned char temp_key[64];  //临时密钥存储
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;
int 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);  //根据口令产生64位密钥
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文件头
void randomkey(unsigned char* random_key);              //产生64位随机序列


int main()
{
	int i, n;
	char filename[256], c;

	printf("***************DES加密CBC模式***************\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);

	randomkey(random_key);
	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位截取,小于补全
{
	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 i, n, j=0;

	while(ftell(fptr)<size)
	{

		fread(&mw[0], 1, 8, fptr);
		
		getbit(m, mw);          //将明文转换为二进制
		if(j==0)
		{
			for(i=0;i<64;i++)
				r_key[i]=random_key[i];
		}
		XOR(m, r_key, 64);
		replace(m, ip, n=64);   //明文的初始置换

		L=&m[0];                //明文分为左右两部分
		R=&m[32];
		
		enrepeat();
		
		replace(L, ip1, 64);        //逆初始置换
		for(i=0;i<64;i++)
			r_key[i]=L[i];
		getchars(L, dmw);

		fwrite(&dmw[0], 1, 8, dfptr);
		j++;
	}

	return;
}

void decode()
{
	int i, n, s=0, j=0;


	while((s=ftell(fptr))<size)
	{
		fread(&mw[0], 1, 8, fptr);

		getbit(m, mw);            //将密文转换为二进制

		L=&m[0];                  //密文分为左右两部分
		R=&m[32];
		if(j==0)
		{
			for(i=0;i<64;i++)
				r_key[i]=random_key[i];
		}
		for(i=0;i<64;i++)
			temp_key[i]=L[i];
		replace(m, ip, n=64);         //密文的初始置换

		derepeat();
		
		replace(L, ip1, 64);          //逆初始置换
		XOR(L, r_key, 64);
		for(i=0;i<64;i++)
			r_key[i]=temp_key[i];
		getchars(L, dmw);

		fwrite(&dmw[0], 1, 8, dfptr);
		j++;
	}
		
	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 ;
}

void randomkey(unsigned char* random_key)
{
	int i;

	srand(time(0));
	for(i=0;i<64;i++)
		random_key[i]=rand()%2;
	return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -