闲来无事,自己研究了一下服务端与客户端之间的文件传输,主要是服务端创建套接字开启监听并等待客户端的连接(TCP),在TCP协议上,为了安全我使用了TLS1.2进行加密通信(OpenSSL库),同时为了文件内容的安全,我在服务端对文件进行了加密(AES),客户端接收到文件后在对其解密。
我用的电脑系统是ubuntu 16.04,不是windows,下面的代码放到windows环境下跑不了的,有些库windows不兼容,但是windows开发的小伙伴也可以参考参考,把不兼容的库替换掉修改修改(比如linux的opendir,readdir,closedir可以替换成windows下的函数,具体百度),应该也可以跑过。无论是windows还是linux,下面的代码中都需要证书,将证书的路径正确的放到代码里面,程序才能编译通过,证书如何生成,请参考我以前的博客。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CA_CRT "./opensslkey/demoCA/cacert1.pem"
#define SERVER_CRT "./opensslkey/server.crt"
#define SERVER_KEY "./opensslkey/server.key"
#define MAXBUF 1024
char buffer[MAXBUF];
char buffer1[MAXBUF];
char *Path = NULL;
void Directory(char* path, SSL* ssl, struct dirent *ptr);
bool readfile(char* my_Path,SSL *ssl,struct dirent *ptr);
bool Document(char* Path, SSL *ssl,struct dirent *ptr);
void aes_box_encrypt(char* source_string, char* des_string, int size);
bool Shutdown(SSL* ssl);
void Getmessage(SSL* ssl, char* buf);
DIR* readFileList(char *basePath);
bool Sendlog(SSL* ssl, char* buf);
void ShowCerts(SSL * ssl);
void aes_box_encrypt(char* source_string, char* des_string, int size)//负责数据加密
{
int iLoop = 0;
int iLen =0;
char buf[1024];
AES_KEY aes;
unsigned char key[AES_BLOCK_SIZE];
unsigned char iv[AES_BLOCK_SIZE];
if(NULL == source_string || NULL == des_string)
{
return;
}
//Generate own AES Key
for(iLoop = 0; iLoop < 16; iLoop++)
{
key[iLoop] = 32 + iLoop;
}
// Set encryption key
for (iLoop=0; iLoop 0)
printf("接收消息成功:'%s',共%d个字节的数据\n", buf, len);
else
printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
}
void Directory(char* path, SSL* ssl, struct dirent *ptr)//目录处理
{
char *base = NULL;
base = path;
strcat(ptr->d_name,"/");
char* e = (char*)malloc(strlen(base) + strlen(ptr->d_name) + 1);
strcpy(e,base);
strcat(e,ptr->d_name);
bool ret = readfile(e, ssl, ptr);
}
bool Document(char* Path, SSL *ssl,struct dirent *ptr)//真正发送log文件
{
char a[1024];
int fd = 0;
memset(a,'\0', sizeof(a));
memset(buffer,'\0', sizeof(buffer));
memset(buffer1,'\0', sizeof(buffer1));
strcpy(a, Path);
strcat(a, ptr->d_name);
fd = open(a, O_RDONLY);
read(fd, buffer,sizeof(buffer));//发送两次数据,第一次是文件名,第二次是文件内容
int len1 = SSL_write(ssl, ptr->d_name, strlen(ptr->d_name));
printf("document name is:%s\n", ptr->d_name);
if (len1 <= 0) {
printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buffer, errno, strerror(errno));
return false;
}
else
printf("消息发送成功,共发送了%d个字节!\n", len1);
aes_box_encrypt(buffer, buffer1, sizeof(buffer));
int len = SSL_write(ssl, buffer1, strlen(buffer1));
if (len <= 0) {
printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buffer, errno, strerror(errno));
return false;
}
else
printf("消息发送成功,共发送了%d个字节!\n", len);
close(fd);
return true;
}
DIR* readFileList(char *basePath)//打开目录,opendir配合readdir使用
{
DIR *dir;
struct dirent *ptr;//readdir
if ((dir=opendir(basePath)) == NULL)
{
printf("Open path error\n");
exit(1);
}
return dir;
}
bool readfile(char* Path,SSL *ssl,struct dirent *ptr)//文件或者目录处理
{
DIR *dir = readFileList(Path);
while ((ptr=readdir(dir)) != NULL)
{
if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0) ///current dir OR parrent dir
continue;
else if(ptr->d_type == 8) //document
{
printf("path is:%s\n",Path);
Document(Path, ssl, ptr);
}
else if(ptr->d_type == 4)//directory
{
Directory(Path, ssl, ptr);
}
}
return true;
}
bool Sendlog(SSL* ssl, char* buf)//发送log文件
{
if(strcmp(buf, "getlog") == 0)
{
struct dirent *ptr;
char *basePath = NULL;
basePath = "./log/";
readfile(basePath, ssl, ptr);
}
Shutdown(ssl);
}
void ShowCerts(SSL * ssl)//验证显示证书
{
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl);
// SSL_get_verify_result()是重点,SSL_CTX_set_verify()只是配置启不启用并没有执行认证,调用该函数才会真证进行证书认证
// 如果验证不通过,那么程序抛出异常中止连接
if(SSL_get_verify_result(ssl) == X509_V_OK){
printf("证书验证通过\n");
}
if (cert != NULL) {
printf("数字证书信息:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("证书: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("颁发者: %s\n", line);
free(line);
X509_free(cert);
}
else
printf("无证书信息!\n");
}