DES、RSA加密的tcp聊天程序

DES、RSA加密的tcp聊天程序

实现主体内容

  • 本试验通过随机生成的RSA公私秘钥用于对DES的随机生成秘钥进行加密
  • 在通过DES加解密算法对服务器客户端之间的数据进行加解密

实现代码

#include <stdio.h>`

#`include <stdlib.h>`

#`include <string.h>`

#`include <time.h>`

#`include <sys/types.h>`

#`include <sys/socket.h>`

#`include <arpa/inet.h>`

#`define SERVERPORT 8888		//服务器监听端口`

#`define BACKLOG 5			//监听队列长度`

#`define BUFFERSIZE 1024		//缓冲区大小`

#`define DESKEYLENGTH 64		//DES密钥长度`

`//公钥结构体`
`struct PublicKey`
`{`
	`long nE;`
	`long nN;`
`};`
`//RSA参数`
`struct RSAParam`
`{`
	`long p;`
	`long q;`
	`long n;`
	`long f;`
	`long e;`
	`long d;`
	`long s;`
`};`

`int pc_first[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`
`};`

`//逆初始置换表`
`int pc_last[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轮迭代运算`
`*/`

`//选择扩展数据表`
`int des_E[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`
`};`

`//置换数据表`
`int des_P[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`
`};`

`int des_S[8][64] = {`
	`//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`
	`}`
`};`

`/*`
	`子密钥生成所需数据表`
`*/`

`//等分密钥`
`int pc_keyleft[28] = {`
	`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`
`};`

`int pc_keyright[28] = {`
	`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`
`};`

`//密钥循环左移运算`
`int moveleft_keynum[16] = {`
	`1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1`
`};`

`//置换选择`
`int keychoose[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`
`};`

`int subkeys[16][48];		//子密钥数组`
`char textdata[32][64];		//保存数据块的地址`

`void DESCore(char* szBuffer);							//DES核心算法`
`void GenerSubkeys(char* key);							//子密钥生成算法`
`int CheckText(char* szBuffer);							//检测文本长度`
`void CleanSpace(char* szBuffer);						//去除空格`
`void CatText(char* szBuffer, int count);				//拼接文本`
`void GetBits(int num, int* data, int pos, int length);	//获取比特位`
`int GetBytes(int* source, int pos, int length);			//获取字节值`
`void DESEncry(char* szBuffer, char key[]);//加密`
`void DESDecry(char* szBuffer, char key[]);//解密`
`void ReverSubKeys();									//调整子密钥的顺序`


`int TotalRecv(int sock, void* szBuffer, size_t length, int flag);	//接受完整消息`
`void DESAllocGener(int sock);		//生成并分配DES密钥`
`void DESAllocRecv(int sock);		//生成RSA公私钥并接收DES密钥`
`void RSAGetParam();			//初始化RSA参数`
`struct PublicKey GetPublicKey();	//获取当前使用的公钥`
`long RSAEncry(unsigned short nSource, struct PublicKey publickey);	//RSA加密`
`unsigned short RSADecry(long nSource);`
`unsigned long MulMod(unsigned long a, unsigned long b, unsigned long n);		//模乘运算`
`unsigned long PowMod(unsigned long base, unsigned long pow, unsigned long n);	//模幂运算`
`long RabinMillerKnl(unsigned long n);						//拉宾——米勒测试`
`long RabinMiller(unsigned long n, unsigned long loop);		//重复拉宾——米勒测试`
`unsigned long RandomPrime(char bits);					//质数生成函数`
`unsigned long Gcd(unsigned long p, unsigned long q);		//求最大公约数`
`unsigned long Enclid(unsigned long e, unsigned long t_n);	//生成私钥d`
`void SecretChat(int sock, char ipaddr[], char chatkey[]);`


`char chatkey[20] = "testtest";`
`struct RSAParam rsa = { 0 };	//RSA参数`
`struct PublicKey publickey;	//RSA公钥`


`//随机生成DES密钥`
`int GenerateDESKey(char* key)`
`{`
	`//生成密钥长度为64bit,即8字节`

	int i, n;
	for (i = 0; i < 8; i++)
	{
		srand(time(NULL));
		n = rand() % 3;
		switch (n)
		{
		case 0:
		{
			//数字
			key[i] = (char)rand() % 58 + 48;
			break;
		}
		case 1:
		{
			//大写字母
			key[i] = (char)rand() % 91 + 65;
			break;
		}
		case 2:
		{
			//小写字母
			key[i] = (char)rand() % 123 + 97;
			break;
		}
		default:
		{
			return 0;
			break;
		}
		}
	}
	key[i] = '\0';
	
	return 1;

`}`

`//DES加密`
`void DESEncry(char* szBuffer, char key[])`
`{`
	`int i;`
	`int count = 0;		//记录消息分割为数据块的数量`

	//检测文本的长度
	count = CheckText(szBuffer);
	
	GenerSubkeys(key);		//生成16个子密钥
	
	//调用加密算法
	for (i = 0; i < count; i++)
	{
		DESCore(textdata[i]);
	}
	
	//拼接文本
	CatText(szBuffer, count);

`}`

`//DES解密`
`void DESDecry(char* szBuffer, char key[])`
`{`
	`int i;`
	`int count = 0;`

	//检测文本的长度
	count = CheckText(szBuffer);
	
	GenerSubkeys(key);		//生成16个子密钥
	ReverSubKeys();			//调整子密钥的顺序
	
	//调用加密算法
	for (i = 0; i < count; i++)
	{
		DESCore(textdata[i]);
	}
	
	//拼接文本
	CatText(szBuffer, count);

`}`

`//DES核心算法`
`void DESCore(char* szBuffer)`
`{`
	`int i, j;							//循环计数器`
	`int temprow, tempcol;				//S盒行列记录`
	`int data[64];						//文本比特位记录`
	`int dataleft[32], dataright[32];	//等分文本比特位`
	`int templeft[64], tempright[48];	//扩展文本比特位`

	//获取64个数据块
	for (i = 0; i < 8; i++)
	{
		GetBits(szBuffer[i], data, i * 8, 8);
	}
	
	//初始置换
	for (i = 0; i < 64; i++)
	{
		templeft[i] = data[pc_first[i] - 1];
	}
	for (i = 0; i < 32; i++)
	{
		dataleft[i] = templeft[i];
		dataright[i] = templeft[i + 32];
	}
	
	//16轮迭代运算
	for (i = 0; i < 16; i++)
	{
		//保存本轮右半段
		for (j = 0; j < 32; j++)
		{
			templeft[j] = dataright[j];
		}
	
		//选择扩展运算
		for (j = 0; j < 48; j++)
		{
			tempright[j] = dataright[des_E[j] - 1];
		}
	
		//密钥加运算
		for (j = 0; j < 48; j++)
		{
			tempright[j] ^= subkeys[i][j];
		}
	
		//选择压缩运算
		for (j = 0; j < 8; j++)
		{
			//计算行号
			temprow = tempright[j * 6] & 1;
			temprow = temprow << 1;
			temprow = tempright[j * 6 + 5] & 1;
			//计算列号
			tempcol = GetBytes(tempright, j * 6 + 1, 4);
	
			GetBits(des_S[j][temprow * 16 + tempcol], tempright, j * 4, 4);
		}
	
		//置换运算
		for (j = 0; j < 32; j++)
		{
			dataright[j] = tempright[des_P[j] - 1];
		}
	
		//与左半段数据异或作为下一轮的右半段,本轮的原始右半段作为下一轮的左半段
		for (j = 0; j < 32; j++)
		{
			dataright[j] ^= dataleft[j];
			dataleft[j] = templeft[j];
		}
	}
	
	//逆初始置换
	for (i = 0; i < 32; i++)
	{
		templeft[i] = dataright[i];
		templeft[i + 32] = dataleft[i];
	}
	
	for (i = 0; i < 64; i++)
	{
		data[i] = templeft[pc_last[i] - 1];
	}
	
	//将加密后的字符串写回缓冲区
	for (i = 0; i < 8; i++)
	{
		szBuffer[i] = GetBytes(data, i * 8, 8);
	}

`}`

`/*`
	`子密钥生成算法由三部分组成:置换选择、循环左移运算、置换运算。`
`*/`

`//子密钥生成算法`
`void GenerSubkeys(char* key)`
`{`
	`int i, j, z;`
	`int templeft, tempright;`
	`int keydata[64], tempbuff[56];`
	`int keyleft[28], keyright[28];`

	for (i = 0; i < 8; i++)
	{
		GetBits(key[i], keydata, i * 8, 8);
	}
	
	//置换选择
	for (i = 0; i < 28; i++)
	{
		keyleft[i] = keydata[pc_keyleft[i] - 1];
		keyright[i] = keydata[pc_keyright[i] - 1];
	}
	
	//循环左移运算
	for (i = 0; i < 16; i++)
	{
		for (j = 0; j < moveleft_keynum[i]; j++)
		{
			templeft = keyleft[0];
			tempright = keyright[0];
			for (z = 0; z < 27; z++)
			{
				keyleft[z] = keyleft[z + 1];
				keyright[z] = keyright[z + 1];
			}
			keyleft[27] = templeft;
			keyright[27] = tempright;
		}
	
		//连接
		for (j = 0; j < 28; j++)
		{
			tempbuff[j] = keyleft[j];
			tempbuff[j + 28] = keyright[j];
		}
	
		//置换选择
		for (j = 0; j < 48; j++)
		{
			subkeys[i][j] = tempbuff[keychoose[j] - 1];
		}
	}

`}`

`/*`
	`辅助函数,用于辅助DES运算`
`*/`

`//检测文本的长度`
`int CheckText(char* szBuffer)`
`{`
	`int i;`
	`int count = 0, length = 0;`

	//检测长度
	length = strlen(szBuffer);
	if (length == 0)
	{
		return count;
	}
	
	//对文本进行分割
	while (length != 0)
	{
		if (length / 8 != 0)
		{
			for (i = 0; i < 8; i++)
			{
				textdata[count][i] = szBuffer[count * 8 + i];
			}
			textdata[count][i] = '\0';
			length -= 8;
			count++;
		}
		else
		{
			if (length == 0)
			{
				break;
			}
			else
			{
				for (i = 0; i < length; i++)
				{
					textdata[count][i] = szBuffer[count * 8 + i];
				}
				for (i = length; i < 8; i++)
				{
					textdata[count][i] = 0x20;
				}
				textdata[count][i] = '\0';
				length = 0;
				count++;
			}
		}
	}
	
	return count;

`}`

`//拼接文本`
`void CatText(char* szBuffer, int count)`
`{`
	`int i, j;`

	for (i = 0; i < count; i++)
	{
		for (j = 0; j < 8; j++)
		{
			szBuffer[i * 8 + j] = textdata[i][j];
		}
	}
	szBuffer[i * 8] = '\0';
	CleanSpace(szBuffer);

`}`

`//去除空格`
`void CleanSpace(char* szBuffer)`
`{`
	`int i;`

	for (i = 0; i < strlen(szBuffer); i++)
	{
		if (szBuffer[i] == 0x20)
		{
			szBuffer[i] = '\0';
		}
	}

`}`

`//获取比特位`
`void GetBits(int num, int* data, int pos, int length)`
`{`
	`int i;`
	`for (i = 0; i < length; i++)`
	`{`
		`data[pos + (length - i - 1)] = (num >> i) & 1;`
	`}`
`}`

`//获取字节值`
`int GetBytes(int* source, int pos, int length)`
`{`
	`int i, result = 0;`

	for (i = 0; i < length; i++)
	{
		result = result | source[pos + i];
		if (i != length - 1)
		{
			result = result << 1;
		}
	}
	
	return result;

`}`

`//调整子密钥的顺序`
`void ReverSubKeys()`
`{`
	`int i, j;`
	`int temp[16][48];`

	for (i = 15; i >= 0; i--)
	{
		for (j = 0; j < 48; j++)
		{
			temp[i][j] = subkeys[15 - i][j];
		}
	}
	for (i = 0; i < 16; i++)
	{
		for (j = 0; j < 48; j++)
		{
			subkeys[i][j] = temp[i][j];
		}
	}

`}`



`//=======================================================`
`//完整接受消息`
`int TotalRecv(int sock, void* szBuffer, size_t length, int flag)`
`{`
	`int nRealSize = 0;`
	`int nReal = 0;`

	//循环接受消息
	while (nReal != -1)
	{
		nReal = recv(sock, ((char*)szBuffer) + nRealSize, length - nRealSize, flag);
		if (nReal + nRealSize > length)
		{
			return -1;
		}
		nRealSize += nReal;
	}
	
	return nRealSize;

`}`




`/*`
	`DES密钥分配`
`*/`

`//生成并发送DES密钥`
`void DESAllocGener(int sock)`
`{`
	`int i, flag;`
	`char szBuffer[BUFFERSIZE];`

	//随机生成DES密钥
	flag = GenerateDESKey(chatkey);
	if (flag)
	{
		printf("Generate DES key successful!\n");
	}
	else
	{
		printf("Generate DES key failed!\n");
		exit(0);
	}
	
	//接收RSA公钥
	flag = recv(sock, (char*)&publickey, BUFFERSIZE, 0);
	if (!flag)
	{
		printf("Receive RSA public key failed!\n");
		exit(0);
	}
	
	//加密DES密钥
	long nEncryDESKey[DESKEYLENGTH / 2];
	unsigned short* pDesKey = (unsigned short*)chatkey;
	for (i = 0; i < DESKEYLENGTH / 2; i++)
	{
		nEncryDESKey[i] = RSAEncry(pDesKey[i], publickey);
	}
	
	//将加密后的DES密钥发送给服务端
	if (sizeof(long) * DESKEYLENGTH / 2 != send(sock, (char*)nEncryDESKey, sizeof(long) * DESKEYLENGTH / 2, 0))
	{
		printf("Send DES key failed!\n");
		exit(0);
	}
	else
	{
		printf("Send DES key successful!\n");
	}

`}`


`//生成RSA公私钥对,并解密DES密钥`
`void ServerToClient(int sock)`
`{`
	`int i;`

	//生成RSA公私钥对
	RSAGetParam();
	publickey = GetPublicKey();
	
	//将公钥发送给客户端
	if (send(sock, (char*)&publickey, sizeof(publickey), 0) != sizeof(publickey))
	{
		printf("Send RSA public key failed!\n");
		exit(0);
	}
	else
	{
		printf("Send RSA public key successful!\n");
	}
	
	//接收加密的DES密钥
	long nEncryDESKey[DESKEYLENGTH / 2];
	if (recv(sock, (char*)nEncryDESKey, DESKEYLENGTH / 2 * sizeof(long), 0) != DESKEYLENGTH / 2 * sizeof(long))
	{
		printf("Receive DES key failed!\n");
		exit(0);
	}
	
	//解密DES密钥
	unsigned short* pDesKey = (unsigned short*)chatkey;
	for (i = 0; i < DESKEYLENGTH / 2; i++)
	{
		pDesKey[i] = RSADecry(nEncryDESKey[i]);
	}

`}`




`/*`
	`RSA`
`*/`

`/*`
	`RSA加解密函数`
`*/`

`//初始化RSA参数`
`void RSAGetParam()`
`{`
	`long t;`

	//随机生成两个素数
	rsa.p = RandomPrime(16);
	rsa.q = RandomPrime(16);
	
	//计算模数及相应的f
	rsa.n = rsa.p * rsa.q;
	rsa.f = (rsa.p - 1) * (rsa.q - 1);
	
	//生成公钥中的e
	do
	{
		rsa.e = rand() % 65536;
		rsa.e |= 1;
	} while (Gcd(rsa.e, rsa.f) != 1);
	
	//生成私钥中的d
	rsa.d = Enclid(rsa.e, rsa.f);
	
	//计算n结尾连续的比特1
	rsa.s = 0;
	t = rsa.n >> 1;
	while (t)
	{
		rsa.s++;
		t >>= 1;
	}

`}`

`//获取公钥函数`
`struct PublicKey GetPublicKey()`
`{`
	`struct PublicKey key;`

	key.nE = rsa.e;
	key.nN = rsa.n;
	
	return key;

`}`

`//RSA加密函数`
`long RSAEncry(unsigned short nSource, struct PublicKey publickey)`
`{`
	`//将字符串转换为二进制块`
	`return PowMod(nSource, publickey.nE, publickey.nN);`
`}`

`//RSA解密函数`
`unsigned short RSADecry(long nSource)`
`{`
	`long nRes = PowMod(nSource, rsa.d, rsa.n);`
	`unsigned short* pRes = (unsigned short*)&nRes;`
	`if (pRes[1] != 0 || pRes[3] != 0 || pRes[2] != 0)`
	`{`
		`return 0;`
	`}`

	return pRes[0];

`}`

`/*`
	`RSA核心函数`
`*/`

`//模乘运算`
`unsigned long MulMod(unsigned long a, unsigned long b, unsigned long n)`
`{`
	`return (a * b) % n;`
`}`

`//模幂运算`
`unsigned long PowMod(unsigned long base, unsigned long pow, unsigned long n)`
`{`
	`unsigned long a = base, b = pow, c = 1;`
	`while (b)`
	`{`
		`while (!(b & 1))`
		`{`
			`b >>= 1;`
			`a = MulMod(a, a, n);`
		`}`
		`b--;`
		`c = MulMod(a, c, n);`
	`}`

	return c;

`}`

`//拉宾——米勒测试,判别是否为质数`
`long RabinMillerKnl(unsigned long n)`
`{`
	`unsigned long a, q, k, v;`
	`unsigned int z;`
	`int i, w;`

	//计算出q,k
	q = n - 1;
	k = 0;
	while (!(q & 1))
	{
		++k;
		q >>= 1;
	}
	
	//随机获取一个数
	a = 2 + rand() % (n - 3);
	v = PowMod(a, q, n);
	if (v == 1)
	{
		return 1;
	}
	
	//循环检验
	for (i = 0; i < k; i++)
	{
		z = 1;
		for (w = 0; w < i; w++)
		{
			z *= 2;
		}
		if (PowMod(a, z * q, n) == n - 1)
		{
			return 1;
		}
	}
	
	return 0;

`}`

`//重复拉宾——米勒测试`
`long RabinMiller(unsigned long n, unsigned long loop)`
`{`
	`int i;`

	for (i = 0; i < loop; i++)
	{
		if (!RabinMillerKnl(n))
		{
			return 0;
		}
	}
	
	return 1;

`}`

`//质数生成函数`
`unsigned long RandomPrime(char bits)`
`{`
	`unsigned long base;`

	do
	{
		base = (unsigned long)1 << (bits - 1);		//保证最高位为1
		base += rand() % base;						//加上一个随机数
		base |= 1;									//保证最低位为1
	} while (!RabinMiller(base, 30));					//进行拉宾——米勒测试30次
	
	return base;

`}`

`//求最大公约数`
`unsigned long Gcd(unsigned long p, unsigned long q)`
`{`
	`unsigned long a = p > q ? p : q;`
	`unsigned long b = p < q ? p : q;`
	`unsigned long t;`

	if (p == q)
	{
		return p;		//若两数相等,最大公约数就是本身
	}
	else
	{
		//辗转相除法
		while (b)
		{
			a = a % b;
			t = a;
			a = b;
			b = t;
		}
	
		return a;
	}

`}`

`//生成私钥中的d`
`unsigned long Enclid(unsigned long e, unsigned long t_n)`
`{`
	`unsigned long max = 0xffffffffffffffff - t_n;`
	`unsigned long i = 1, tmp;`

	while (1)
	{
		if (((i * t_n) + 1) % e == 0)
		{
			return ((i * t_n) + 1) / e;
		}
		i++;
		tmp = (i + 1) * t_n;
		if (tmp > max)
		{
			return 0;
		}
	}
	
	return 0;

`}`


`//======================================`

`//选择执行的身份`
`char ChooseCorS()`
`{`
	`char id;`
	`char input[10];`

	printf("Client or Server?\n");
	scanf("%s", input);
	
	//输入检查
	if (strcmp(input, "c") && strcmp(input, "C") && strcmp(input, "client") && strcmp(input, "Client"))
	{
		if (strcmp(input, "s") && strcmp(input, "S") && strcmp(input, "server") && strcmp(input, "Server"))
		{
			printf("Input error!");
			id = 'e';
		}
		else
		{
			id = 's';
		}
	}
	else
	{
		id = 'c';
	}
	
	return id;

`}`


`//安全聊天`
`void SecretChat(int sock, char ipaddr[], char chatkey[])`
`{`
	`pid_t pid;	//进程标识符`
	`char szInputBuffer[BUFFERSIZE], szRecvBuffer[BUFFERSIZE];`
	`int length = 0;`

	//检查密钥的长度
	if (strlen(chatkey) != 8)
	{
		printf("key length error!\n");
		return;
	}
	
	//创建子进程,进行并发通信
	//如果pid=0,则表示为子进程,否则为父进程
	//父进程负责接收消息后解密并输出到标准输出,子进程负责获取标准输入加密并发送
	pid = fork();
	if (pid != 0)
	{
		//父进程,负责接收消息
		while (1)
		{
			length = recv(sock, szRecvBuffer, BUFFERSIZE, 0);
			if (length <= 0)
			{
				printf("Receive failed!\n");
			}
			else
			{
				DESDecry(szRecvBuffer, chatkey);
				printf("Receive message from<%s>: %s\n", ipaddr, szRecvBuffer);
			}
	
			if (!strcmp(szRecvBuffer, "quit"))
			{
				printf("Quit chat!\n");
				break;
			}
		}
	}
	else
	{
		//子进程,负责发送消息
		while (1)
		{
			scanf("%s", szInputBuffer);
			if (strlen(szInputBuffer) <= 0)
			{
				printf("Input error!\n");
				continue;
			}
			DESEncry(szInputBuffer, chatkey);
			length = send(sock, szInputBuffer, strlen(szInputBuffer) + 1, 0);
			if (length <= 0)
			{
				printf("Send failed!\n");
			}
	
			if (!strcmp(szInputBuffer, "quit"))
			{
				printf("Quit chat!\n");
				break;
			}
		}
	}

`}`

`//服务器连接客户端`
`int ServerToClient()`
`{`
	`int server, client, length;`
	`struct sockaddr_in localaddr;`
	`struct sockaddr_in remoteaddr;`

	//建立服务器socket
	if ((server = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("Create socket failed!");
		return 0;
	}
	
	//设置服务器地址结构
	localaddr.sin_family = AF_INET;
	localaddr.sin_port = htons(SERVERPORT);
	localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	
	//绑定监听端口
	if (bind(server, (struct sockaddr*)&localaddr, sizeof(struct sockaddr)) == -1)
	{
		perror("Bind port failed!");
		return 0;
	}
	
	//开始监听
	if (listen(server, BACKLOG) == -1)
	{
		perror("Listen failed!");
		return 0;
	}
	printf("Listening...\n");
	
	//接收连接请求
	length = sizeof(struct sockaddr_in);
	if ((client = accept(server, (struct sockaddr*)&remoteaddr, &length)) == -1)
	{
		perror("Accept socket failed!");
		return 0;
	}
	printf("Server: got connection from %s, port %d, socket %d\n", inet_ntoa(remoteaddr.sin_addr), ntohs(remoteaddr.sin_port), client);
	close(server);
	
	//DES密钥分配
	DESAllocRecv(client);
	
	//连接建立,开始聊天
	printf("Begin chat ...\n");
	SecretChat(client, inet_ntoa(remoteaddr.sin_addr), chatkey);
	
	//关闭socket
	close(client);
	
	return 1;

`}`

`//客户端连接服务器`
`int ClientToServer(char serverIpAddr[])`
`{`
	`int client;`
	`struct sockaddr_in serveraddr;`

	//建立客户端socket
	if ((client = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("Create socket failed!");
		return 0;
	}
	
	//设置服务器地址结构
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(SERVERPORT);
	serveraddr.sin_addr.s_addr = inet_addr(serverIpAddr);
	
	//连接服务器
	if (connect(client, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) != 0)
	{
		perror("Client connect failed!");
		return 0;
	}
	printf("Connect Success!\n");
	
	//DES密钥分配
	DESAllocGener(client);
	
	//连接已经建立,开始聊天
	printf("Begin chat ...\n");
	SecretChat(client, serverIpAddr, chatkey);
	
	//关闭socket
	close(client);
	
	return 1;

`}`

`int main(int argc, char* argv[]){`
	`char id;				//身份标记`
	`char serveraddr[20];	//服务器IP地址`

	//选择执行的身份
	id = ChooseCorS();
	
	//启动服务
	switch (id)
	{
	case 'c':
	{
		//获取服务器地址
		printf("Please input the server address:\n");
		scanf("%s", serveraddr);
		if (strlen(serveraddr) <= 0 || strlen(serveraddr) > 16)
		{
			printf("Server address input error!");
		}
		else
		{
			//建立连接
			ClientToServer(serveraddr);
		}
	
		break;
	}
	case 's':
	{
		//监听连接
	
		ServerToClient();
	
		break;
	}
	default:
	{
		printf("Id error!");
		break;
	}
	}
	
	return 0;

`}`


代码解释

  • 主体调用为开启客户端,服务器端调用RSA公私秘钥生成函数随机生成公私秘钥,在将RSA公钥发送给客户端
  • 客户端调用DES随机秘钥生成函数,接收服务器端发送的RSA公钥,用收到的公钥加密DES秘钥,在将加密的DES秘钥发送给服务器端
  • 服务器端接受加密DES秘钥,用RSA私钥解密获得DES秘钥
  • 服务器和客户端在调用安全聊天函数进行安全聊天

实现结果

10.JPG

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值