2019-2020-1 20,175,209 Experiment 5 protocol design

2019-2020-1 20,175,209 Experiment 5 protocol design

- # Experiment:

  • 1. In Ubuntu completion http://www.cnblogs.com/rocedu/p/5087623.htmlof the job.

  • 2. Job
    • In pairs.

    • Socket-based implementation of the TCP communication, a person achieve server, a client of people realize.

    • OpenSSL algorithm research, test symmetrical algorithm AES, asymmetric algorithm RSA, Hash algorithm MD5.

    • Choose the appropriate algorithm, hybrid cryptosystem Based carried confidentiality, integrity, protection of TCP traffic.

    • There is spare capacity person, the system safety analysis and improvement.

  • 3. In Ubuntu implemented in two experimental "WC server" are protected by a hybrid cryptosystem.

  • 4. Run the test chamber, ARM calls Z32 test algorithm, submit test shots. (To be done)

  • 5. Z32 of state secret algorithm rewrite "wc server" hybrid password protection, submit run shot. (To be done)

Experimental Procedure:

SSL / TLS Protocol Overview

  • In 1994 Netscape developed SSL (Secure Socket Layer, Secure Sockets Layer protocol), designed to protect Web traffic.

  • It uses public key technology, the goal is to ensure that the application between the two communication security and reliability, can be achieved simultaneously support both ends of the server and the client.

  • Current Web browsers in general will be a combination of HTTP and SSL, enabling secure communications.

Using the SSL protocol

SSL is independent of the various protocols, commonly used in the HTTP protocol, but other protocols can also be used, such as SMTP, TELNET and the like.

协议的目标:SSL/TLS被设计用来使用TCP提供一个可靠的端到端安全服务,为两个通讯个体之间提供保密性和完整性(身份鉴别)。

SSL / TLS provides three standard services: confidentiality, message integrity and mutual authentication.

SSL architecture

Agreement is divided into two tiers:

Bottom: SSL Record Protocol provides basic security services to upper layer protocols.

Top: SSL handshake protocol, SSL protocol instructions to change the password, SSL warning protocol used to manage SSL exchange process.

OpenSSL installation under Linux

  • Locate the appropriate environment in the blog link teacher to the park and click download.

  • Enter the command in the File extract the files in the download directory.

tar xzvf openssl-1.1.0-pre1.tar.gz

  • After the extraction is completed using the cd openssl-1.1.0-pre1command unzip the file into the directory, do the following:
$ ./config

$ make

$ make test  \\测试一下有没有问题。

$ sudo make install

[If any of these steps fails, see section Installation in Detail below.][如果这些步骤中的任何一个失败,请参见下面的详细安装部分。]
  • ./config run shot

  • make run shot

  • make test run shot

  • sudo make install run shot

Use of Linux, 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 -lssl -lcrypto -ldl -lpthread

  • 实现echo $?进行执行,结果打印了一个0,截图如下

基于Socket实现TCP通信,一人实现服务器,一人实现客户端

  • 客户端传一个文本文件给服务器。

  • 服务器返加文本文件中的单词数。

研究OpenSSL算法,测试对称算法中的AES,非对称算法中的RSA,Hash算法中的MD5

AES算法

  • 对称加密:对称加密需要使用的标准命令为enc
openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e] [-d] [-a/-base64]
   [-A] [-k password] [-kfile filename] [-K key] [-iv IV] [-S salt] [-salt] [-nosalt] [-z] [-md]
   [-p] [-P] [-bufsize number] [-nopad] [-debug] [-none] [-engine id]
   
-in filename:指定要加密的文件存放路径

-out filename:指定加密后的文件存放路径

-salt:自动插入一个随机数作为文件内容加密,默认选项

-e:可以指明一种加密算法,若不指的话将使用默认加密算法

-d:解密,解密时也可以指定算法,若不指定则使用默认算法,但一定要与加密时的算法一致

-a/-base64:使用-base64位编码格式

使用下列命令对my.txt进行加密:

openssl enc -aes-128-cbc -in my.txt -out out.txt -pass pass:123456   

RSA算法:

  • RSA的用法如下:
openssl rsa [-inform PEM|NET|DER] [-outform PEM|NET|DER] [-in filename] [-passin arg] [-out filename] [-passout arg]
   [-sgckey] [-des] [-des3] [-idea] [-text] [-noout] [-modulus] [-check] [-pubin] [-pubout] [-engine id]
常用选项:

-in filename:指明私钥文件

-out filename:指明将提取出的公钥保存至指定文件中 

-pubout:根据私钥提取出公钥

RSA是一个非对称加密算法。简单说来,非对称加密算法就是说加密解密一个文件需要有两个密钥,一个用来加密,为公钥,一个用来解密,为私钥。证书可以用来授权公钥的使用。

  • 首先需要进入openssl的交互界面,在命令行了输入
openssl
  • 生成RSA私钥
genrsa -out rsa_private_key.pem 1024

该命令会生成1024位的私钥,此时我们就可以在当前路径下看到rsa_private_key.pem文件了。

  • 生成RSA公钥
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

并回车,得到生成成功的结果,如下图:

  • 加密文件:

在目录中创建一个hello的文本文件,然后利用此前生成的公钥加密文件:

 openssl rsautl -encrypt -in hello.txt -inkey rsa_public_key.pem -pubin -out hello.e

-in指定要加密的文件,

-inkey指定密钥,

-pubin表明是用纯公钥文件加密,

-out为加密后的文件。

  • 解密文件:

使用命令

openssl rsautl -decrypt -in hello.e -inkey rsa_private_key.pem -out hello.de

-in指定被加密的文件,

-inkey指定私钥文件,

-out为解密后的文件。

MD5

用oppnssl md5 加密字符串和文件的方法。

在终端中输入openssl后回车。
  

OpenSSL> md5        //输入md5后回车
      
hello 20175213 woaini           //接着输入明文,不要输入回车。然后按3次ctrl+d。
 
hello 20175213 woaini(stdin)= 09be1a60e70c26fa6885ba52baaa71d6 //等号后面就是密文

实现对“wc服务器”的混合密码系统防护

  • server服务器代码:
#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客户端代码:
#include <stdio.h>  
#include <string.h>  
#include <errno.h>  
#include <sys/socket.h>  
#include <resolv.h>  
#include <stdlib.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <unistd.h>  
#include <openssl/ssl.h>  
#include <openssl/err.h>
 #include <openssl/evp.h>
  
  
#define MAXBUF 1024  
  
void ShowCerts(SSL * ssl)  
{  
    X509 *cert;  
    char *line;  
  
    cert = SSL_get_peer_certificate(ssl);  
    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");  
}  
  
int main(int argc, char **argv)  
{  
    int sockfd, len;  
    struct sockaddr_in dest;  
    char buffer[MAXBUF + 1];  
    SSL_CTX *ctx;  
    SSL *ssl;  
  
    if (argc != 3) {  
        printf("参数格式错误!正确用法如下:\n\t\t%s IP地址 端口\n\t比如:\t%s 127.0.0.1 80\n此程序用来从某个"  
             "IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",  
             argv[0], argv[0]);  
        exit(0);  
    }  
  
    /* SSL 库初始化,参看 ssl-server.c 代码 */  
    SSL_library_init();  
    OpenSSL_add_all_algorithms();  
    SSL_load_error_strings();  
    ctx = SSL_CTX_new(SSLv23_client_method());  
    if (ctx == NULL) {  
        ERR_print_errors_fp(stdout);  
        exit(1);  
    }  
  
    /* 创建一个 socket 用于 tcp 通信 */  
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {  
        perror("Socket");  
        exit(errno);  
    }  
    printf("socket created\n");  
  
    /* 初始化服务器端(对方)的地址和端口信息 */  
    bzero(&dest, sizeof(dest));  
    dest.sin_family = AF_INET;  
    dest.sin_port = htons(atoi(argv[2]));  
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {  
        perror(argv[1]);  
        exit(errno);  
    }  
    printf("address created\n");  
  
    /* 连接服务器 */  
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {  
        perror("Connect ");  
        exit(errno);  
    }  
    printf("server connected\n");  
  
    /* 基于 ctx 产生一个新的 SSL */  
    ssl = SSL_new(ctx);  
    SSL_set_fd(ssl, sockfd);  
    /* 建立 SSL 连接 */  
    if (SSL_connect(ssl) == -1)  
        ERR_print_errors_fp(stderr);  
    else {  
        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));  
        ShowCerts(ssl);  
    }  
  
    /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */  
    bzero(buffer, MAXBUF + 1);  
    /* 接收服务器来的消息 */  
    len = SSL_read(ssl, buffer, MAXBUF);  
    if (len > 0)  
        printf("接收消息成功:'%s',共%d个字节的数据\n",  
               buffer, len);  
    else {  
        printf  
            ("消息接收失败!错误代码是%d,错误信息是'%s'\n",  
             errno, strerror(errno));  
        goto finish;  
    }  
    bzero(buffer, MAXBUF + 1);  
    strcpy(buffer, "from client->server");  
    /* 发消息给服务器 */  
    len = SSL_write(ssl, buffer, strlen(buffer));  
    if (len < 0)  
        printf  
            ("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n",  
             buffer, errno, strerror(errno));  
    else  
        printf("消息'%s'发送成功,共发送了%d个字节!\n",  
               buffer, len);  
  
  finish:  
    /* 关闭连接 */  
    SSL_shutdown(ssl);  
    SSL_free(ssl);  
    close(sockfd);  
    SSL_CTX_free(ctx);  
    return 0;  
}  
  • 客户端/服务器端编译方式:
gcc -o server server.c -I /usr/local/ssl/include -L/usr/local/ssl/lib -lssl -lcrypto -ldl -lpthread

gcc -o client client.c -I /usr/local/ssl/include -L/usr/local/ssl/lib -lssl -lcrypto -ldl -lpthread
  • 生产私钥和证书:
openssl genrsa -out privkey.pem 1024

openssl req -new -x509 -key privkey.pem -out CAcert.pem -days 1095

  • 客户端/服务器端运行方式:
./server 7838 1 CAcert.pem privkey.pem

./client 127.0.0.1 7838
  • 运行截图:

实验中遇到的问题及解决方法

问题1:

使用gcc -o to test_openssl.c -I /usr/local/ssl/inlcude -L /usr/local/ssl/lib -ldl -lpthread编译 test_openssl.c 报错

问题1解决方法:

使用 gcc -o test_openssl test_openssl.c -L/usr/local/ssl/lib -lcrypto -ldl -lpthread 进行编译,成功生成可执行文件,并且运行成功。

问题2:

运行中出现openssl: error while loading shared libraries: libssl.so.3: cannot open shared object file: No such file or directory的错误

问题2解决方法:

经过上网查询,发现是因为找不到库的位置造成的,但按照网上的方法
输入命令sudo ln -s /usr/local/lib/libssl.so.3 /usr/lib/libssl.so.3sudo ln -s /usr/local/lib/libcrypto.so.3 /usr/lib/libcrypto.so.3后,发现还是没有解决。
后继续在网上寻求解决方法,发现是因为文件已经存在了,所以需要把软连接删掉。使用sudo rm -rf /usr/lib/libssl.so.3sudo rm -rf /usr/lib/libcrypto.so.3 命令将它们删掉。再使用上述命令就可解决此问题。

Guess you like

Origin www.cnblogs.com/wangzihong0213/p/11970242.html