2017-2018-1 20155314《信息安全系统设计基础》实验五 通讯协议设计
通讯协议设计-1
实验要求
在Ubuntu中完成 http://www.cnblogs.com/rocedu/p/5087623.html 中的作业
提交运行结果截图
学到的知识
Linux下的应用大多可以直接使用,也可以获取源代码自己进行编译、安装,使用源代码安装的过程一般是:
- configure
- make
- make install
gcc -o test_openssl test_openssl.c -I /usr/local/ssl/include -L /usr/local/ssl/lib -lcrypto -ldl -lpthread
上面这句表示在编译test_openssl.c时:
- -o test_openssl test_openssl.c:
将test_openssl.c编译生成可执行文件test_openssl(如果不给出这个选项,gcc就给出预设的可执行文件a.out)
- -I /usr/local/ssl/include:
将/usr/local/ssl/include目录作为第一个寻找头文件的目录,寻找的顺序是:/usr/local/ssl/include-->/usr/include-->/usr/local/include
- -L /usr/local/ssl/lib:
将/usr/local/ssl/lib目录作为第一个寻找库文件的目录,寻找的顺序是:/usr/local/ssl/lib-->/lib-->/usr/lib-->/usr/local/lib
- -L:指定链接库的文件夹地址
- -ldl:加载动态库
- -lcrypto:导入OpenSSL所需包
- -lpthread:链接POSIX thread库
实验步骤
一、Linux下OpenSSL的安装
-
访问OpenSSL的官网http://www.openssl.org/source/,下载最新版本的OpenSSL:这里为了跟老师的教程同步,我选择下载教程给出的OpenSSL版本:OpenSSL 1.1.0alpha
-
在Ubuntu ARM V12B V2.0虚拟机中使用
tar xzvf openssl-1.1.0-pre1.tar.gz
命令解压源代码; -
使用
cd openssl-1.1.0-pre1
命令进入源代码目录; -
使用下列命令编译安装:
$ ./config $ make $ sudo make install
-
使用
make test
命令测试安装是否正确:测试全部通过,表明安装无误~
二、Linux下OpenSSL的使用
OpenSSL应用程序
- 通过
man openssl
查看帮助文档:
OpenSSL密码算法库
-
编写一个测试代码test_openssl.c:
#include <stdio.h> #include <openssl/evp.h> int main(){ OpenSSL_add_all_algorithms(); return 0; }
-
使用
gcc -o test_openssl test_openssl.c -L/usr/local/ssl/lib -lcrypto -ldl -lpthread
命令编译生成可执行文件test_openssl
-
执行
echo $?
,结果打印0,表明测试通过,如下图:
通讯协议设计-2
实验要求
在Ubuntu中实现对实验二中的“wc服务器”通过混合密码系统进行防护
提交测试截图
学到的知识
-
混合密码系统介绍
-
OpenSSL流程
- 初始化
- 选择会话协议和创建会话环境
- 建立SSL套接字
- 完成SSL握手
- 从SSL套接字中提取对方的证书信息
- 数据传输
- 结束SSL通信
-
OpenSSL应用编程框架
-
Server端:
ctx = SSL_CTX_new (SSLv23_server_method()); ssl = SSL_new (ctx); fd = socket (); bind (); listen (); accept (); SSL_set_fd (ssl, fd); SSL_accept (ssl); SSL_read ();
-
Client端:
ctx = SSL_CTX_new (SSLv23_client_method()); ssl = SSL_new (ctx); fd = socket (); connect (); SSL_set_fd (ssl, fd); SSL_connect (ssl); SSL_write ();
-
实验代码
-
server.c:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #include <unistd.h> #include <arpa/inet.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/evp.h> #define MAXBUF 1024 int main(int argc, char **argv) { int sockfd, new_fd; socklen_t len; struct sockaddr_in my_addr, their_addr; unsigned int myport, lisnum; char buf[MAXBUF + 1]; SSL_CTX *ctx; if (argv[1]) myport = atoi(argv[1]); else myport = 7838; if (argv[2]) lisnum = atoi(argv[2]); else lisnum = 2; /* SSL 库初始化 */ SSL_library_init(); /* 载入所有 SSL 算法 */ OpenSSL_add_all_algorithms(); /* 载入所有 SSL 错误消息 */ SSL_load_error_strings(); /* 以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text */ ctx = SSL_CTX_new(SSLv23_server_method()); /* 也可以用 SSLv2_server_method() 或 SSLv3_server_method() 单独表示 V2 或 V3标准 */ if (ctx == NULL) { ERR_print_errors_fp(stdout); exit(1); } /* 载入用户的数字证书, 此证书用来发送给客户端。 证书里包含有公钥 */ if (SSL_CTX_use_certificate_file(ctx, argv[3], SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stdout); exit(1); } /* 载入用户私钥 */ if (SSL_CTX_use_PrivateKey_file(ctx, argv[4], SSL_FILETYPE_PEM) <= 0){ ERR_print_errors_fp(stdout); exit(1); } /* 检查用户私钥是否正确 */ if (!SSL_CTX_check_private_key(ctx)) { ERR_print_errors_fp(stdout); exit(1); } /* 开启一个 socket 监听 */ if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } else printf("socket created\\n"); bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = PF_INET; my_addr.sin_port = htons(myport); my_addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } else printf("binded\\n"); if (listen(sockfd, lisnum) == -1) { perror("listen"); exit(1); } else printf("begin listen\\n"); while (1) { SSL *ssl; len = sizeof(struct sockaddr); /* 等待客户端连上来 */ if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &len)) == -1) { perror("accept"); exit(errno); } else printf("server: got connection from %s, port %d, socket %d\\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd); /* 基于 ctx 产生一个新的 SSL */ ssl = SSL_new(ctx); /* 将连接用户的 socket 加入到 SSL */ SSL_set_fd(ssl, new_fd); /* 建立 SSL 连接 */ if (SSL_accept(ssl) == -1) { perror("accept"); close(new_fd); break; } /* 开始处理每个新连接上的数据收发 */ bzero(buf, MAXBUF + 1); strcpy(buf, "server->client"); /* 发消息给客户端 */ len = SSL_write(ssl, buf, strlen(buf)); if (len <= 0) { printf ("\'%s\'发送失败!错误代码:%d,错误信息:\'%s\'\\n", buf, errno, strerror(errno)); goto finish; } else printf("\'%s\'发送成功!共发送%d个字节!\\n", buf, len); bzero(buf, MAXBUF + 1); /* 接收客户端的消息 */ len = SSL_read(ssl, buf, MAXBUF); if (len > 0) printf("\'%s\'接收成功!共接收%d个字节的数据!\\n", buf, len); else printf ("接收失败!错误代码:%d,错误信息:\'%s\'\\n", errno, strerror(errno)); /* 处理每个新连接上的数据收发结束 */ finish: /* 关闭 SSL 连接 */ SSL_shutdown(ssl); /* 释放 SSL */ SSL_free(ssl); /* 关闭 socket */ close(new_fd); } /* 关闭监听的 socket */ close(sockfd); /* 释放 CTX */ SSL_CTX_free(ctx); return 0;
-
client.c:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #include <unistd.h> #include <arpa/inet.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/evp.h> #define MAXBUF 1024 int main(int argc, char **argv) { int sockfd, new_fd; socklen_t len; struct sockaddr_in my_addr, their_addr; unsigned int myport, lisnum; char buf[MAXBUF + 1]; SSL_CTX *ctx; if (argv[1]) myport = atoi(argv[1]); else myport = 7838; if (argv[2]) lisnum = atoi(argv[2]); else lisnum = 2; /* SSL 库初始化 */ SSL_library_init(); /* 载入所有 SSL 算法 */ OpenSSL_add_all_algorithms(); /* 载入所有 SSL 错误消息 */ SSL_load_error_strings(); /* 以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text */ ctx = SSL_CTX_new(SSLv23_server_method()); /* 也可以用 SSLv2_server_method() 或 SSLv3_server_method() 单独表示 V2 或 V3标准 */ if (ctx == NULL) { ERR_print_errors_fp(stdout); exit(1); } /* 载入用户的数字证书, 此证书用来发送给客户端。 证书里包含有公钥 */ if (SSL_CTX_use_certificate_file(ctx, argv[3], SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stdout); exit(1); } /* 载入用户私钥 */ if (SSL_CTX_use_PrivateKey_file(ctx, argv[4], SSL_FILETYPE_PEM) <= 0){ ERR_print_errors_fp(stdout); exit(1); } /* 检查用户私钥是否正确 */ if (!SSL_CTX_check_private_key(ctx)) { ERR_print_errors_fp(stdout); exit(1); } /* 开启一个 socket 监听 */ if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } else printf("socket created\\n"); bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = PF_INET; my_addr.sin_port = htons(myport); my_addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } else printf("binded\\n"); if (listen(sockfd, lisnum) == -1) { perror("listen"); exit(1); } else printf("begin listen\\n"); while (1) { SSL *ssl; len = sizeof(struct sockaddr); /* 等待客户端连上来 */ if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &len)) == -1) { perror("accept"); exit(errno); } else printf("server: got connection from %s, port %d, socket %d\\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd); /* 基于 ctx 产生一个新的 SSL */ ssl = SSL_new(ctx); /* 将连接用户的 socket 加入到 SSL */ SSL_set_fd(ssl, new_fd); /* 建立 SSL 连接 */ if (SSL_accept(ssl) == -1) { perror("accept"); close(new_fd); break; } /* 开始处理每个新连接上的数据收发 */ bzero(buf, MAXBUF + 1); strcpy(buf, "server->client"); /* 发消息给客户端 */ len = SSL_write(ssl, buf, strlen(buf)); if (len <= 0) { printf ("\'%s\'发送失败!错误代码:%d,错误信息:\'%s\'\\n", buf, errno, strerror(errno)); goto finish; } else printf("\'%s\'发送成功!共发送%d个字节!\\n", buf, len); bzero(buf, MAXBUF + 1); /* 接收客户端的消息 */ len = SSL_read(ssl, buf, MAXBUF); if (len > 0) printf("\'%s\'接收成功!共接收%d个字节的数据!\\n", buf, len); else printf ("接收失败!错误代码:%d,错误信息:\'%s\'\\n", errno, strerror(errno)); /* 处理每个新连接上的数据收发结束 */ finish: /* 关闭 SSL 连接 */ SSL_shutdown(ssl); /* 释放 SSL */ SSL_free(ssl); /* 关闭 socket */ close(new_fd); } /* 关闭监听的 socket */ close(sockfd); /* 释放 CTX */ SSL_CTX_free(ctx); return 0;
}
运行截图
通讯协议设计-3
实验要求
运行实验箱中,ARM调用Z32算法的实验,提交实验截图
用Z32的国密算法重新改写“wc服务器”的混合密码系统防护,提交运行截图
运行结果
- 未要求完成
实验中遇到的问题及解决过程
OpenSSL编译安装问题
-
问题描述:
OpenSSL安装过程中
make install
时报错:
-
主要原因:
被老师博客教程中写的
./configure
所困惑:
我在OpenSSL安装目录中并没有找到可执行文件configure
,但却发现了两个与之非常相似的可执行文件config
和Configure
,于是便不假思索地输入命令./Configure
,导致到make install
这一步时出错,错误原因未知... -
解决方法:
正解自然是用
./config
命令执行可执行文件config
,再make
和make install
,该问题便迎刃而解了: