在之前的代码中我们并没有对套接字进行加密,在未加密状态下我们所有的通信内容都是明文传输的,这种方式在学习时可以使用但在真正的开发环境中必须要对数据包进行加密,此处笔者将演示一种基于时间的加密方法,该加密方法的优势是数据包每次发送均不一致,但数据包内的内容是一致的,当抓包后会发现每次传输的数据包密文是随机变化的,但内容始终保持一致,也就是说两个拥有相同内容的数据被加密后,数据包密文不同,其主要运用了基于当前时间戳的通信机制。
14.11.1 实现加盐函数
加盐函数此处笔者采用基于时间的加盐方式,取出用户分钟数与秒数并生成随机数作为盐,通过三者的混合计算出一串解密密钥对,此方法的必须保证服务端与客户端时间同步,如果不同步则无法计算出正确的密钥对,解密也就无法继续了。
代码中函数GenRandomString
用于实现生成一个随机数,该函数接受一个随机数长度并返回一个字符串。接着GetPasswordSalt_OnSec
与GetPasswordSalt_OnMin
函数分别用于根据当前秒与分钟生成一个随机的盐,函数GetXorKey
则用于对特定一段字符串进行异或处理并生成一个Key,函数CRC32
则用于对字符串计算得到一个哈希值。
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <random>
#include <time.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
typedef struct
{
char random[1024];
char Buffer[4096];
}SocketPackage;
// 产生长度为length的随机字符串
char* GenRandomString(int length)
{
int flag, i;
char* string;
srand((unsigned)time(NULL));
if ((string = (char*)malloc(length)) == NULL)
{
return NULL;
}
for (i = 0; i < length - 1; i )
{
flag = rand() % 3;
switch (flag)
{
case 0:
string[i] = 'A' rand() % 26;
break;
case 1:
string[i] = 'a' rand() % 26;
break;
case 2:
string[i] = '0' rand() % 10;
break;
default:
string[i] = 'x';
break;
}
}
string[length - 1] = '