2017-2018-1 20155314《信息安全系统设计基础》实验五 通讯协议设计

Posted 20155314刘子健

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017-2018-1 20155314《信息安全系统设计基础》实验五 通讯协议设计相关的知识,希望对你有一定的参考价值。

2017-2018-1 20155314《信息安全系统设计基础》实验五 通讯协议设计

通讯协议设计-1

实验要求

学到的知识

  1. Linux下的应用大多可以直接使用,也可以获取源代码自己进行编译、安装,使用源代码安装的过程一般是:

    • configure
    • make
    • make install
  2. 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的安装

  1. 访问OpenSSL的官网http://www.openssl.org/source/,下载最新版本的OpenSSL:这里为了跟老师的教程同步,我选择下载教程给出的OpenSSL版本:OpenSSL 1.1.0alpha

  2. 在Ubuntu ARM V12B V2.0虚拟机中使用tar xzvf openssl-1.1.0-pre1.tar.gz命令解压源代码;

  3. 使用cd openssl-1.1.0-pre1命令进入源代码目录;

  4. 使用下列命令编译安装:

    $ ./config
    $ make
    $ sudo make install
    
  5. 使用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

实验要求

  1. 运行实验箱中,ARM调用Z32算法的实验,提交实验截图

  2. 用Z32的国密算法重新改写“wc服务器”的混合密码系统防护,提交运行截图

运行结果

  • 未要求完成

实验中遇到的问题及解决过程

OpenSSL编译安装问题

  • 问题描述:

    OpenSSL安装过程中make install时报错:

  • 主要原因:

    被老师博客教程中写的./configure所困惑:
    我在OpenSSL安装目录中并没有找到可执行文件configure,但却发现了两个与之非常相似的可执行文件configConfigure,于是便不假思索地输入命令./Configure,导致到make install这一步时出错,错误原因未知...

  • 解决方法:

    正解自然是用./config命令执行可执行文件config,再makemake install,该问题便迎刃而解了:

参考资料

以上是关于2017-2018-1 20155314《信息安全系统设计基础》实验五 通讯协议设计的主要内容,如果未能解决你的问题,请参考以下文章

2017-2018-1 20155314 《信息安全系统设计基础》第13周学习总结

2017-2018-1 20155314 《信息安全系统设计基础》第11周学习总结

20155314 《信息安全系统设计基础》课程总结

20155313 2017-2018-1 《信息安全系统设计基础》课程总结

2017-2018-1 《信息安全系统设计基础》课程总结

2017-2018-1 20155331+20155336《信息安全系统设计基础》实验一报告