zoukankan      html  css  js  c++  java
  • 2018-2019-1 20165222 20165216 实验五 通讯协议设计

    实验五 通讯协议设计

    任务一:Linux下OpenSSL的安装与使用

    一、OpenSSL的安装

    ①: 访问OpenSSL官网++http:/www.openssl.org/source/++ 下载OpenSSL1.1.0

    ②:在Ubuntu虚拟机中使用tar xzvf openssl-1.1.0-pre1.tar.gz命令解压源代码

    ③:命令cd opensll-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,表明测试通过。

    任务二:在Ubuntu中实现实验二中的“wc服务器”通过混合密码系统进行保护

    混合密码系统介绍图

    OpenSSL保护原理

    SSL协议

    SSL(Secure Sockets Layer 安全套接层)协议
    ,是为网络通信提供安全及数据完整性的一种安全协议,SSL协议已成为全球化标准,所有主要的浏览器和WEB服务器程序都支持SSL协议,可通过安装SSL证书激活SSL协议。

    证书

    数字化文件,包含公共密钥和其他的属性,具有不可否认性。

    OpenSSL囊括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议.
    • Openssl协定会话采用协议,TLSv1.0/SSLv2/SSLv3.
    • 创建相应SSL环境
    • 设定相关证书验证
    • 选定需要使用的加密算法,并生成密钥对

    / openssl genrsa -des3 -out server.key 1024
    genras表示生成RSA私有密钥文件,-des3表示用DES3加密该文件/

    代码展示

    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
    ");
    
          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
    ");
    
          if (listen(sockfd, lisnum) == -1) {
              perror("listen");
              exit(1);
          } else
              printf("begin listen
    ");
    
          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
    ",
                         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'
    ",
                       buf, errno, strerror(errno));
                  goto finish;
              } else
                  printf("'%s'发送成功!共发送%d个字节!
    ",
                         buf, len);
    
              bzero(buf, MAXBUF + 1);
              /* 接收客户端的消息 */
              len = SSL_read(ssl, buf, MAXBUF);
              if (len > 0)
                  printf("'%s'接收成功!共接收%d个字节的数据!
    ",
                         buf, len);
              else
                  printf
                      ("接收失败!错误代码:%d,错误信息:'%s'
    ",
                       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;
      }
    

    serve.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
    ");
    
          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
    ");
    
          if (listen(sockfd, lisnum) == -1) {
              perror("listen");
              exit(1);
          } else
              printf("begin listen
    ");
    
          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
    ",
                         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'
    ",
                       buf, errno, strerror(errno));
                  goto finish;
              } else
                  printf("'%s'发送成功!共发送%d个字节!
    ",
                         buf, len);
    
              bzero(buf, MAXBUF + 1);
              /* 接收客户端的消息 */
              len = SSL_read(ssl, buf, MAXBUF);
              if (len > 0)
                  printf("'%s'接收成功!共接收%d个字节的数据!
    ",
                         buf, len);
              else
                  printf
                      ("接收失败!错误代码:%d,错误信息:'%s'
    ",
                       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;
      }
    

    实验截图

  • 相关阅读:
    我对管理信息系统定位的理解
    正斜杠和反斜杠-windows、web、c语言大讨论
    java异常处理的两种方法
    使用throws抛出异常
    课后作业
    每日自学
    《梦断代码》读后感
    每日自学
    每日自学
    每日自学
  • 原文地址:https://www.cnblogs.com/qq2497879550/p/10127119.html
Copyright © 2011-2022 走看看