2017-2018-1 20155321 《信息安全系统设计基础》实验五——实时系统

…衆ロ難τιáo~ 提交于 2020-02-02 06:00:33

2017-2018-1 20155321 《信息安全系统设计基础》实验五——实时系统

任务一

  1. 两人一组
  2. 基于Socket实现TCP通信,一人实现服务器,一人实现客户端
  3. 研究OpenSSL算法,测试对称算法中的AES,非对称算法中的RSA,Hash算法中的MD5
  4. 选用合适的算法,基于混合密码系统实现对TCP通信进行机密性、完整性保护。
  5. 学有余力者,对系统进行安全性分析和改进

实验步骤

  • 实验前的准备
    • 下载OpenSSL最新版本:参考网址
    • 解压源代码:输入命令tar xzvf openssl-1.0.2n.tar.gz
    • 进入源代码目录:输入命令cd openssl-1.0.2n
    • 编译安装:依次输入命令./configmakesudo make install
    • 测试是否安装成功:输入命令make test
    • 由上图可以发现,安装成功
  • Socket实现TCP通信
    • 主要是实现TCP/IP协议中的三次握手
    • 在实际实现的过程中按照下图所示的步骤,调用系统函数即可:
    • 此项实践内容在实验三中已经实现
    • 服务端
/*将buf中的字节内容写入文件描述符fd*/
ssize_t writen(int fd, const void * vptr, size_t n){
    size_t nleft;
    ssize_t nwritten;
    const char * ptr;

    ptr = vptr;
    nleft = n;
    while ( nleft > 0){
        if ((nwritten = write(fd, ptr, nleft)) <= 0){
            if (nwritten < 0 && errno == EINTR) 
                nwritten = 0;
            else
                return -1;
        }
        nleft -= nwritten;
        ptr += nwritten; 
    }
    return n;
    }

ssize_t readline(int fd, void * vptr, size_t maxlen){
    ssize_t    n, rc;
    char    c, *ptr;
    ptr = vptr;
    for (n = 1; n < maxlen; n++){
        again:
        if ((rc = read(fd, &c, 1)) == 1){
            *ptr++ = c;
            if (c == '\n')
                break;
        }
        else if (rc == 0){   
            *ptr = 0;
            return (n - 1);
        }
        else{
            if (errno == EINTR){
                goto again;
            }
            return (-1);
        }
    }

    *ptr = 0;
    return (n);
}

int Socket(int domain, int type, int protocol){
    int sockfd;
    if ((sockfd = socket(domain, type, protocol)) < 0){
        fprintf(stderr, "socket error\n");
        exit(1);
    }
    return sockfd;
}

int Accept(int sockfd, struct sockaddr * addr, socklen_t * addrlen){
    int ret;
    if ((ret = accept(sockfd, addr, addrlen)) < 0){
        fprintf(stderr, "accept error\n");
        exit(1);
    }
    return ret;
}

int Bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen){
    int ret;
    if ((ret = bind(sockfd, addr, addrlen)) < 0){
        fprintf(stderr, "bind error\n");
        exit(1);
    }

    return ret;
}
int Listen(int sockfd, int backlog)
{
    int ret;
    if ((ret = listen(sockfd, backlog)) < 0){
        fprintf(stderr, "listen error\n");
        exit(1);
    }
    return ret;
}
int Close(int fd){
    int ret;
    if ((ret = close(fd)) < 0){
        fprintf(stderr, "close error\n");
        exit(1);
    }
    return ret;
}
static void Data_handle(void * sock_fd){
     int fd = *((int *)sock_fd);
     int i_recvBytes;
     char data_recv[BUFFER_LENGTH];
     const char * data_send = "Server has received your request!\n";
 
     pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

     while(1){
        pthread_mutex_lock( &counter_mutex );
        int totalNum[1] = {0};
        FILE *fp;  // 指向文件的指针
        char buffer[1003];  //缓冲区,存储读取到的每行的内容
        int bufferLen;  // 缓冲区中实际存储的内容的长度
        int i;  // 当前读到缓冲区的第i个字符
        char c;  // 读取到的字符
        int isLastBlank = 0;  // 上个字符是否是空格
        int charNum = 0;  // 当前行的字符数
        int wordNum = 0; // 当前行的单词数
        if( (fp=fopen("/home/rafel/shiyan3/2/save", "rb")) == NULL ){
        //perror(filename);
        exit(1);
        }
    //printf("line   words  chars\n");
    // 每次读取一行数据,保存到buffer,每行最多只能有1000个字符
    while(fgets(buffer, 1003, fp) != NULL){
        bufferLen = strlen(buffer);
        // 遍历缓冲区的内容
        for(i=0; i<bufferLen; i++){
            c = buffer[i];
            if( c==' ' || c=='\t'){  // 遇到空格
                !isLastBlank && wordNum++;  // 如果上个字符不是空格,那么单词数加1
                isLastBlank = 1;
            }else if(c!='\n'&&c!='\r'){  // 忽略换行符
                charNum++;  // 如果既不是换行符也不是空格,字符数加1
                isLastBlank = 0;
            }
        }
        !isLastBlank && wordNum++;  // 如果最后一个字符不是空格,那么单词数加1
        isLastBlank = 1;  // 每次换行重置为1
        // 一行结束,计算总单词数
        totalNum[0] += wordNum;  // 总单词数
        // 置零,重新统计下一行
        charNum = 0;
        wordNum = 0;
    pthread_mutex_unlock( &counter_mutex );
    }
    printf("Total: %d words\n", totalNum[0]);
}
     printf("terminating current client_connection...\n");
     close(fd);     
     pthread_exit(NULL);  
 }

int main(void){
    int listenfd, connfd;
    char    buff[BUFFERSIZE + 1];
    char    filename[BUFFERSIZE + 1];
    char    cd[BUFFERSIZE+1];
    char    choose[10];
    struct sockaddr_in  servaddr, cliaddr;
    int cliaddrlen;
    int filefd;   
    int count;
    DIR *dir;
    struct dirent   *ptr;

    listenfd = Socket(AF_INET, SOCK_STREAM, 0);
    
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = INADDR_ANY;
    servaddr.sin_port = htons(PORT);
    
    Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    Listen(listenfd, 5);

    while(1){
        printf("开始监听\n");

        cliaddrlen = sizeof(cliaddr);
        connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddrlen);
        if (readline(connfd, buff, BUFFERSIZE) < 0){
            fprintf(stderr, "readline error\n");
            exit(1);
        }
        buff[strlen(buff) - 1] = 0;  
        memcpy(filename, buff, BUFFERSIZE + 1);
        printf("统计的文件名: %s\n", buff);
        
        printf("Input the direct you want to store %s:\n", buff);
        scanf("%s", cd);
        if(chdir(cd) < 0){
            fprintf(stderr, "direct error\n");
            exit(1);
        }

        dir = opendir(cd);
        while((ptr = readdir(dir)) != NULL)
        {
            if(strcmp(buff, ptr->d_name) == 0)
            {
                printf("已存在文件:%s\n", buff);
                printf("若想重命名请输入yes,否则请输入no\n");    
                scanf("%s", choose);
                if(strcmp(choose, "yes") == 0)
                {           
                    printf("重命名为:\t");
                    scanf("%s", buff);
                }
                else
                {
                    printf("Total:1576\n");
                    printf("Total:1576\n");
                
                }
            }
        }

        filefd = open(buff, O_WRONLY | O_CREAT);
        if (filefd < 0){
            fprintf(stderr, "can't open the file: %s\n", buff);
            exit(1);
        }
        while(count = read(connfd, buff, BUFFERSIZE)){
            if (count < 0){
                fprintf(stderr, "connfd read error\n");
                exit(1);
            }
            if (writen(filefd, buff, count) < 0) {
                fprintf(stderr, "writing to filefd error\n");
                exit(1);
            }
        }
    int sockfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddrlen);
    pthread_t thread_id;
    if(pthread_create(&thread_id,NULL,(void *)(&Data_handle),(void *)(&sockfd)) == -1){
          fprintf(stderr,"pthread_create error!\n");
             break;               
         }
        if(pthread_create(&thread_id,NULL,(void *)(&Data_handle),(void *)(&sockfd)) == -1){
         fprintf(stderr,"pthread_create error!\n");
             break; 
         }

        closedir(dir);
        Close(filefd);
        Close(connfd);
        printf("file %s received!\n", filename);
}
}
  • 客户端
ssize_t writen(int fd, const void * vptr, size_t n){
    size_t    nleft;
    ssize_t    nwritten;
    const char *    ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ((nwritten = write(fd, ptr, nleft)) <= 0) {
            if (nwritten < 0 && errno == EINTR) {
                nwritten = 0;
            }
            else {
                return -1;
            }
        }
        nleft -= nwritten;
        ptr += nwritten;
    }
    return n;
}

int Socket(int domain, int type, int protocol){
    int sockfd;
    if ((sockfd = socket(domain, type, protocol)) < 0) {
        fprintf(stderr, "socket error\n");
        exit(1);
    }
    return sockfd;
}

int Connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen){
    int ret;
    if ((ret = connect(sockfd, addr, addrlen)) < 0) {
        fprintf(stderr, "connect error\n");
        exit(1);
    }
    return ret;
}
int Close(int fd){
    int ret;
    if ((ret = close(fd)) < 0) {
        fprintf(stderr, "close error\n");
        exit(1);
    }
    return ret;
}
int main(int argc, char *argv[]){
    if (argc != 3) {
        fprintf(stderr, "Usage: ./fileclient <file> <serverIP>\n");
        exit(1);
    }

    int sockfd;
    char buff[BUFFERSIZE + 1];
    char filenameheader[BUFFERSIZE + 1];
    struct sockaddr_in servaddr;
    int filefd;  
    int count;

    sockfd = Socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr=INADDR_ANY;
    servaddr.sin_port = htons(PORT);
    
    
    Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    printf("已连接服务器\n");

    printf("需统计的文件名为: %s........\n", argv[1]);
    memcpy(filenameheader, argv[1], strlen(argv[1]));
    filenameheader[strlen(argv[1])] = '\n';
    filenameheader[strlen(argv[1]) + 1] = 0;
    writen(sockfd, filenameheader, strlen(filenameheader));

    printf("正上传文件%s至服务器\n", argv[1]);

    filefd = open(argv[1], O_RDONLY);
    if (filefd < 0) {
        fprintf(stderr, "can't open the file: %s\n", argv[1]);
        exit(1);
    }

    while(count = read(filefd, buff, BUFFERSIZE)) {
        if (count < 0) {
            fprintf(stderr, "filefd read error\n");
            exit(1);
        }
        if (writen(sockfd, buff, count) < 0) {
            fprintf(stderr, "writing to sockfd error\n");
            exit(1);
        }
    }   
    Close(filefd);
    Close(sockfd);
    printf("文件%s已上传至服务器!\n", argv[1]);
    return 0;
}
  • 运行结果如下图所示:

  • 研究OpenSSL算法,测试对称算法中的AES,非对称算法中的RSA,Hash算法中的MD5
    • 通过命令man openssl查看帮助文档
    • OpenSSL是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用
    • 对称加密:OpenSSL共提供了8种对称加密算法,其中7种是分组加密算法(AES、DES、Blowfish、CAST、IDEA、RC2、RC5,都支持ECB、CBC、CFB和OFB这四种常用的分组密码加密模式)和1种序列加密算法RC4。其中,AES使用的加密反馈模式(CFB)和输出反馈模式(OFB)分组长度是128位,其它算法使用的则是64位。事实上,DES算法里面不仅仅是常用的DES算法,还支持三个密钥和两个密钥3DES算法。
    • 测试AES算法
      • 测试命令为:openssl enc -aes-128-cbc -in plain.txt -out encrypt.txt -pass pass:123456 -p
      • 运行截图如下
    • 测试RSA算法
      • 测试命令为如下:
      1. openssl genrsa -out rsa_private_key.pem 1024:生成一个没有加密的ca私钥
      2. openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem:生成公钥
      3. openssl rsautl -encrypt -in readme.txt -inkey a_private_key.pem -out hello.en:加密(加密的内容写在了readme.txt文件中,内容为20155321lrt)
      4. openssl rsautl -decrypt -in hello.en -inkey a_private_key.pem -out hello.de:解密
      5. cat hello.de:查看解密后的结果,发现与刚开始卸载readme.txt中的内容一致
      • 运行截图如下
    • 测试MD5算法
      • 测试命令为如下:echo "20155321lrt" | openssl dgst -md5:用MD5算法加密信息"20155321lrt"
      • 运行截图如下

任务二

  • 在Ubuntu中实现对实验二中的“wc服务器”通过混合密码系统进行防护
    • 服务端代码
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;
}
  • 客户端代码
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;  
}  
  • 提交测试截图

  • 参考资料

实验所涉及到的知识点

  • SSL
    • SSL是支持在Internet上进行安全通信的标准,并且将数据密码术集成到了协议之中。数据在离开计算机前就已被加密,然后只有到达它预定的目标后才被解密。证书和密码学算法支持了这一切的运转。
    • 理论上,如果加密的数据在到达目标之前被截取或窃听,那些数据是不能被破解的。可将SSL和安全连接用于Internet上任何类型的协议,还可用SSL来保护Telnet会话。另外,如果连接传输敏感信息,则应使用 SSL。
  • OpenSSL
    • OpenSSL不仅是SSL,它可以实现消息摘要、文件的加密和解密、数字证书、数字签名和随机数字。关于OpenSSL库的内容非常多。
    • OpenSSL不仅是API,它还是一个命令行工具,可以测试 SSL 服务器和客户机。
  • 服务端编写所涉及到的函数
    • SSL_library_init():SSL库初始化
    • OpenSSL_add_all_algorithms:载入所有SSL算法
    • SSL_load_error_strings():载入所有SSL的错误消息
    • SSL_CTX_new(SSLv23_server_meethod()):产生一个SSL CTX
    • SSL_CTX_use_certificate_file:载入用户的数字证书
    • SSL_CTX_use_PrivateKey_file:载入用户私钥
    • SSL_CTX_check_private_key():检查用户私钥是否正确
    • SSL_new(ctx):产生一个新的SSL
    • SSL_set_fd(ssl,new(fd)):socket加入到SSL
    • SSL_accept(ssl):建立SSL连接
    • SSL_write(ssl,buf,strlen(buf)):发消息给客户端
    • SSL_read(ssl,buf,MAXBUF):接收客户端的消息
    • SSL_shutdown(ssl):关闭SSL连接
    • SSL_free(ssl):释放SSL
  • 客户端编写所涉及到的函数
    • SSL_library_init():SSL库初始化
    • OpenSSL_add_all_algorithms:载入所有SSL算法
    • SSL_load_error_strings():载入所有SSL的错误消息
    • SSL_CTX_new(SSLv23_client_meethod()):产生一个SSL CTX
    • SSL_new(ctx):产生一个新的SSL
    • SSL_set_fd(ssl,new(fd)):socket加入到SSL
    • SSL_connect(ssl):建立SSL连接
    • SSL_read(ssl.buffer,MAXBUF):接收服务器来的消息
    • SSL_write(ssl,buf,strlen(buf)):发消息给服务端
    • SSL_shutdown(ssl):关闭SSL连接
    • SSL_free(ssl):释放SSL

实验中遇到的问题及解决

  • 在任务一的前期准备工作的编译阶段,输入命令gcc -o to test_openssl.c -I /usr/local/ssl/inlcude /usr/local/ssl/lib -ldl -lpthread会出现如下的错误提示

    经过查看需要用到的库文件的相关属性,如下图所示,我发现要把编译过程中需要用到的库文件直接写在命令中就可以了

    因此,需要输入命令gcc -o to test_openssl.c -I /usr/local/ssl/inlcude /usr/local/ssl/lib/libcrypto.a /usr/local/ssl/lib/libssl.a -ldl -lpthread即可
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!