OpenSSL编程模型
客户端模型
1.初始化
2.创建SSL
3.数据收发
4.关闭
编译程序
gcc -lssl client.c -o client 编译PC版
arm-linux-gcc -L .../_install/lib/ -lssl -lcrypto -I .../_install/include/ client.c -o client 编译ARM版
服务器模型
1.初始化
2.载入数字证书和私钥
3.创建SSL
4.数据收发
5.关闭
编译程序
gcc -lssl server.c -o server
测试程序
当客户端连接到服务器时,服务器会把对应的数字证书发送给客户端,在以后的通讯过程中就用发送的数据证书和服务器的私钥进行加密和解密。
创建私钥
openssl genrsa -out privkey.pem 2048 genrsa表示创建私钥,-out privkey.pem输出私钥文件名,2048表示位数
创建数字证书
openssl req -new -x509 -key privkey.pem -out certkey.pem -days 1095
client.c
/******************************************************************** *名称:client.c *作者:D *时间:2016.04.03 *功能:网络安全传输系统客户端 *********************************************************************/ /******************************************************************** *头文件 *********************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/socket.h> #include <netinet/in.h> #include <openssl/ssl.h> #include <openssl/err.h> /******************************************************************** *宏定义 *********************************************************************/ #define SERVER_PORT 3333 //网络端口 /******************************************************************** *函数原型 *********************************************************************/ int main(int argc, char **argv); void menu(SSL *ssl); void upload(SSL *ssl); void download(SSL *ssl); void quit(SSL *ssl); /******************************************************************** *名称:main *参数: * argc 参数数量 * argv 参数列表 *返回: * stat 0 成功 * -1 失败 *功能:主函数 *********************************************************************/ int main(int argc, char **argv){ //参数检查 if(argc != 2){ printf("Usage: ./client <ip address> "); return -1; } //创建 SSL SSL_CTX *ctx; SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); ctx = SSL_CTX_new(SSLv23_client_method()); //客户端模式 //创建标识 int clientfd; clientfd = socket(AF_INET, SOCK_STREAM, 0); if(clientfd == -1){ printf("Can not create socket! "); return -1; } //建立连接 struct sockaddr_in serverAddr; int isConnect; serverAddr.sin_family = AF_INET; //设置协议 serverAddr.sin_port = htons(SERVER_PORT); //设置端口 serverAddr.sin_addr.s_addr = inet_addr(argv[1]); //设置地址 bzero(serverAddr.sin_zero, 8); //设置为零 isConnect = connect(clientfd, (struct sockaddr *)&serverAddr, sizeof(struct sockaddr)); if(isConnect == -1){ printf("Can not connect to server! "); return -1; } //连接 SSL SSL *ssl; ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); SSL_connect(ssl); //显示菜单 menu(ssl); //关闭 SSL SSL_shutdown(ssl); SSL_free(ssl); //关闭连接 close(clientfd); //释放 SSL SSL_CTX_free(ctx); return 0; } /******************************************************************** *名称:menu *参数: * ssl 客户端标志 *返回: * none *功能:显示菜单 *********************************************************************/ void menu(SSL *ssl){ //显示菜单 while(1){ //打印菜单 printf(" "); printf("********************************************************************** "); printf("* Client * "); printf("*[1]Upload Files * "); printf("*[2]Download Files * "); printf("*[3]Exit * "); printf("********************************************************************** "); printf("Please Select: "); //输入命令 int num; scanf("%d", &num); //处理命令 switch(num){ //上传文件 case 1: upload(ssl); break; //下载文件 case 2: download(ssl); break; //退出程序 case 3: quit(ssl); break; //错误命令 default: printf(" Please input again! "); break; } //是否退出 if(num == 3){ break; } } } /******************************************************************** *名称:upload *参数: * ssl 客户端标志 *返回: * none *功能:上传文件 *********************************************************************/ void upload(SSL *ssl){ //输入文件名称 char filename[20]; printf(" Upload file: "); scanf("%s", &filename); //打开上传文件 int fd; fd = open(filename, O_RDONLY); if(fd == -1){ printf("Can not open file! "); return ; } //发送上传命令 char cmd = 'U'; SSL_write(ssl, (void *)&cmd, sizeof(cmd)); //发送文件名称 int namesize; namesize = strlen(filename) + 1; //加上字符串接收符 SSL_write(ssl, (void *)&namesize, sizeof(namesize)); SSL_write(ssl, (void *)&filename, namesize); //发送文件长度 struct stat fstat; int isState; isState = stat(filename, &fstat); if(isState == -1){ printf("Can not get file state! "); return ; } SSL_write(ssl, (void *)&(fstat.st_size), sizeof(fstat.st_size)); //发送文件内容 char buf[1024]; int num; num = read(fd, (void *)buf, sizeof(buf)); while(num > 0){ //发送文件内容 SSL_write(ssl, (void *)&buf, num); //读取文件内容 num = read(fd, (void *)buf, sizeof(buf)); } //关闭上传文件 close(fd); } /******************************************************************** *名称:download *参数: * ssl 客户端标志 *返回: * none *功能:下载文件 *********************************************************************/ void download(SSL *ssl){ //输入文件名称 char filename[20]; printf(" Download file: "); scanf("%s", &filename); //创建下载文件 int fd; fd = open(filename, O_RDWR | O_CREAT, 0777); if(fd == -1){ printf("Can not create file! "); return ; } //发送下载命令 char cmd = 'D'; SSL_write(ssl, (void *)&cmd, sizeof(cmd)); //发送文件名称 int namesize; namesize = strlen(filename) + 1; //加上字符串接收符 SSL_write(ssl, (void *)&namesize, sizeof(namesize)); SSL_write(ssl, (void *)&filename, namesize); //接收文件长度 int fileszie; SSL_read(ssl, &fileszie, sizeof(fileszie)); //接收文件内容 char buf[1024]; int num; num = SSL_read(ssl, (void *)buf, sizeof(buf)); while(num > 0){ //写入接收内容 write(fd, (void *)&buf, num); //是否接收结束 fileszie = fileszie - num; if(fileszie == 0){ break; } //接收文件内容 num = SSL_read(ssl, (void *)buf, sizeof(buf)); } //关闭下载文件 close(fd); } /******************************************************************** *名称:quit *参数: * ssl 客户端标志 *返回: * none *功能:退出程序 *********************************************************************/ void quit(SSL *ssl){ //发送退出命令 char cmd = 'Q'; SSL_write(ssl, (void *)&cmd, sizeof(cmd)); //清除屏幕显示 system("clear"); }
server.c
/******************************************************************** *名称:server.c *作者:D *时间:2016.04.05 *功能:网络安全传输系统服务端 *********************************************************************/ /******************************************************************** *头文件 *********************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/socket.h> #include <netinet/in.h> #include <openssl/ssl.h> #include <openssl/err.h> /******************************************************************** *宏定义 *********************************************************************/ #define SERVER_PORT 3333 //网络端口 /******************************************************************** *函数原型 *********************************************************************/ int main(int argc, char **argv); void menu(SSL *ssl); void upload(SSL *ssl); void download(SSL *ssl); /******************************************************************** *名称:main *参数: * argc 参数数量 * argv 参数列表 *返回: * stat 0 成功 * -1 失败 *功能:主函数 *********************************************************************/ int main(int argc, char **argv){ //创建 SSL SSL_CTX *ctx; SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); ctx = SSL_CTX_new(SSLv23_server_method()); //服务器模式 //配置 SSL int isCert, isPriv; isCert = SSL_CTX_use_certificate_file(ctx, "./certkey.pem", SSL_FILETYPE_PEM); //载入数字证书 if(isCert == -1){ ERR_print_errors_fp(stdout); return -1; } isPriv = SSL_CTX_use_PrivateKey_file(ctx, "./privkey.pem", SSL_FILETYPE_PEM); //载入用户私钥 if(isPriv == -1){ ERR_print_errors_fp(stdout); return -1; } //检测 SSL int isCheck; isCheck = SSL_CTX_check_private_key(ctx); if(isCheck == 0){ ERR_print_errors_fp(stdout); return -1; } //创建标识 int serverfd; serverfd = socket(AF_INET, SOCK_STREAM, 0); if(serverfd == -1){ printf("Can not create socket! "); return -1; } //绑定地址 struct sockaddr_in serverAddr; int isBand; serverAddr.sin_family = AF_INET; //设置协议 serverAddr.sin_port = htons(SERVER_PORT); //设置端口 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); //设置地址 bzero(serverAddr.sin_zero, 8); //设置为零 isBand = bind(serverfd, (struct sockaddr *)&serverAddr, sizeof(struct sockaddr)); if(isBand == -1){ printf("Can not bind! "); return -1; } //监听端口 int isListen; isListen = listen(serverfd, 5); if(isListen == -1){ printf("Can not listen! "); return -1; } //处理连接 while(1){ //等待连接 socklen_t clientAddrLen; struct sockaddr_in clientAddr; int clientfd; clientAddrLen = sizeof(struct sockaddr); clientfd = accept(serverfd, (struct sockaddr *)&clientAddr, &clientAddrLen); if(clientfd == -1){ printf("Can not accept! "); return -1; } //连接 SSL SSL *ssl; int isAccept; ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); isAccept = SSL_accept(ssl); if(isAccept == -1){ ERR_print_errors_fp(stdout); return -1; } //处理菜单 menu(ssl); //关闭 SSL SSL_shutdown(ssl); SSL_free(ssl); //关闭连接 close(clientfd); } //关闭连接 close(serverfd); //释放 SSL SSL_CTX_free(ctx); } /******************************************************************** *名称:menu *参数: * ssl 客户端标志 *返回: * none *功能:处理菜单 *********************************************************************/ void menu(SSL *ssl){ //处理菜单 while(1){ //读取命令 char cmd; SSL_read(ssl, (void *)&cmd, sizeof(cmd)); //处理命令 switch(cmd){ //上传文件 case 'U': upload(ssl); break; //下载文件 case 'D': download(ssl); break; //退出程序 case 'Q': break; //其他命令 default: break; } //是否退出 if(cmd == 'Q'){ break; } } } /******************************************************************** *名称:upload *参数: * ssl 客户端标志 *返回: * none *功能:上传文件 *********************************************************************/ void upload(SSL *ssl){ //接收文件名称 int namesize; char filename[20]; SSL_read(ssl, (void *)&namesize, sizeof(namesize)); SSL_read(ssl, (void *)&filename, namesize); //创建上传文件 int fd; fd = open(filename, O_RDWR | O_CREAT, 0777); if(fd == -1){ printf("Can not create file! "); return ; } //接收文件长度 int fileszie; SSL_read(ssl, &fileszie, sizeof(fileszie)); //接收文件内容 char buf[1024]; int num; num = SSL_read(ssl, (void *)buf, sizeof(buf)); while(num > 0){ //写入接收内容 write(fd, (void *)&buf, num); //是否接收结束 fileszie = fileszie - num; if(fileszie == 0){ break; } //接收文件内容 num = SSL_read(ssl, (void *)buf, sizeof(buf)); } //关闭上传文件 close(fd); } /******************************************************************** *名称:download *参数: * ssl 客户端标志 *返回: * none *功能:下载文件 *********************************************************************/ void download(SSL *ssl){ //接收文件名称 int namesize; char filename[20]; SSL_read(ssl, (void *)&namesize, sizeof(namesize)); SSL_read(ssl, (void *)&filename, namesize); //打开下载文件 int fd; fd = open(filename, O_RDONLY); if(fd == -1){ printf("Can not open file! "); return ; } //发送文件长度 struct stat fstat; int isState; isState = stat(filename, &fstat); if(isState == -1){ printf("Can not get file state! "); return ; } SSL_write(ssl, (void *)&(fstat.st_size), sizeof(fstat.st_size)); //发送文件内容 char buf[1024]; int num; num = read(fd, (void *)buf, sizeof(buf)); while(num > 0){ //发送文件内容 SSL_write(ssl, (void *)&buf, num); //读取文件内容 num = read(fd, (void *)buf, sizeof(buf)); } //关闭下载文件 close(fd); }