首页 > 系统相关 >Linux 实现OpenSSL 服务器端客户端通信

Linux 实现OpenSSL 服务器端客户端通信

时间:2023-10-20 15:15:40浏览次数:38  
标签:服务器端 ssl printf OpenSSL argv SSL Linux include


1.OpenSSL安装

详情参考博文:https://blog.csdn.net/qq_39521181/article/details/96457673

2.SSL

在学习openssl编程之前,先了解一下什么是SSL,有助于后续的学习。SSL 是一个缩写,代表的是 Secure Sockets Layer。它是支持在 Internet 上进行安全通信的标准,并且将数据密码术集成到了协议之中。数据在离开您的计算机之前就已经被加密,然后只有到达它预定的目标后才被解密。证书和密码学算法支持了这一切的运转,使用 OpenSSL,您将有机会切身体会它们。

理论上,如果加密的数据在到达目标之前被截取或窃听,那些数据是不可能被破解的。不过,由于计算机的变化一年比一年快,而且密码翻译方法有了新的发展,因此,SSL 中使用的加密协议被破解的可能性也在增大。可以将 SSL 和安全连接用于 Internet 上任何类型的协议,不管是 HTTP、POP3,还是 FTP。还可以用 SSL 来保护 Telnet 会话。虽然可以用 SSL 保护任何连接,但是不必对每一类连接都使用 SSL。如果连接传输敏感信息,则应使用 SSL。

3.openssl
OpenSSL 不仅仅是 SSL。它可以实现消息摘要、文件的加密和解密、数字证书、数字签名和随机数字。关于 OpenSSL 库的内容非常多,远不是一篇文章可以容纳的。OpenSSL 不只是 API,它还是一个命令行工具。命令行工具可以完成与 API 同样的工作,而且更进一步,可以测试 SSL 服务器和客户机。

4.基本功能
OpenSSL整个软件包大概可以分成三个主要的功能部分:SSL协议库、应用程序以及密码算法库。OpenSSL的目录结构自然也是围绕这三个功能部分进行规划的。
作为一个基于密码学的安全开发包,OpenSSL提供的功能相当强大和全面,囊括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议,并提供了丰富的应用程序供测试或其它目的使用。
辅助功能
BIO机制是OpenSSL提供的一种高层IO接口,该接口封装了几乎所有类型的IO接口,如内存访问、文件访问以及Socket等。这使得代码的重用性大幅度提高,OpenSSL提供API的复杂性也降低了很多。
OpenSSL对于随机数的生成和管理也提供了一整套的解决方法和支持API函数。随机数的好坏是决定一个密钥是否安全的重要前提。
OpenSSL还提供了其它的一些辅助功能,如从口令生成密钥的API,证书签发和管理中的配置文件机制等等。如果你有足够的耐心,将会在深入使用OpenSSL的过程慢慢发现很多这样的小功能,让你不断有新的惊喜。

5.实现通信实例

 

服务器端:

//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>#define MAXBUF 1024int 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]);elsemyport = 7788;if (argv[2])lisnum = atoi(argv[2]);elselisnum = 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);} elseprintf("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);} elseprintf("binded\n");if (listen(sockfd, lisnum) == -1) {perror("listen");exit(1);} elseprintf("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);} elseprintf("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;} elseprintf("消息'%s'发送成功,共发送了%d个字节!\n",buf, len);bzero(buf, MAXBUF + 1);/* 接收客户端的消息 */len = SSL_read(ssl, buf, MAXBUF);if (len > 0)printf("接收消息成功:'%s',共%d个字节的数据\n",buf, len);elseprintf("消息接收失败!错误代码是%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 <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>#define MAXBUF 1024void 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);} elseprintf("无证书信息!\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_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));elseprintf("消息'%s'发送成功,共发送了%d个字节!\n",buffer, len);finish:/* 关闭连接 */SSL_shutdown(ssl);SSL_free(ssl);close(sockfd);SSL_CTX_free(ctx);return 0;
}

 

6.编译

gcc -o client client.c -Wall -g -lssl -lcrypto        //客户端
gcc -o server server.c -Wall -g -lssl -lcrypto     //服务端

说明:切记ssl和crypto库要加上,否则编译失败。

 

7.程序运行:

./server 7788 1 CAcert.pem fkey.pem
./client 127.0.0.1 7788

标签:服务器端,ssl,printf,OpenSSL,argv,SSL,Linux,include
From: https://www.cnblogs.com/lcword/p/17777122.html

相关文章

  • openssl基础使用(密码学 linux)
    目录       实验原理       实验过程           一、对称加密               1、使用rc4加解密               2、使用AES加解密               3、使用3DES加解密           二、非对......
  • 小明哥学linux驱动之USB-OTG(基于gadget框架)【转】
    转自:https://blog.csdn.net/silence3039/article/details/100187666一、简介OTG是On-The-Go的缩写。其设计的初衷是为了两个“外设”在没有PC(Host)的情况下,也可以通过USB进行数据传输。可以理解为,拥有OTG功能的USB设备(OTG设备)既可以做host,也可以做peripheral。二、OTG基本结构2......
  • linux上部署ftp server
    在github上找到了2个还算活跃的方案:https://github.com/fauria/docker-vsftpdhttps://github.com/stilliard/docker-pure-ftpd方案一  https://github.com/fauria/docker-vsftpd1、创建容器dockerrun-d-v/my/data/directory:/home/vsftpd\-p20:20-p21:21-p2110......
  • Linux学习-1
    学习笔记-命令汇总文件管理绝对路径 cd以绝对路径进入某个文件夹  pwd查看当前工作目录的绝对路径相对路径 cd ..表示当前目录的上层目录,.表示当前目录 目录操作创建:mkdir (-p创建多层目录)查看:pwd(当前所在目录)(-p实际工作目录)ls-a查看隐藏的目录与文件 ls......
  • openssl api使用
    实验要求参考https://blog.csdn.net/bruce135lee/article/details/81811403调用OpenSSLAPI0推荐在openEuler中实现,参考https://www.cnblogs.com/rocedu/p/6012545.html第三节1提交相关代码码云(或github)链接2提交不少于6张编译测试过程截图3至少包含SM4,SM3的测试代码......
  • Linux升级openssl、openssh
     在项目中,我们经常会发现Linux系统中OpenSSH、OpenSSL存在高危漏洞,如OpenSSL“心脏出血”漏洞,利用该漏洞,黑客可以获取约30%的https开头网址的用户登录账号密码,其中包括购物、网银、社交、门户等类型的知名网站等。以及OpenSSH漏洞,如“OpenSSH远程代码执行漏洞CVE-2016-10009......
  • 实验二 OpenSSL API使用
    sm3代码#include<stdio.h>#include<openssl/evp.h>#include<openssl/err.h>#include<openssl/rand.h>voidhandleErrors(void){ERR_print_errors_fp(stderr);abort();}voidtest_sm3(){unsignedchardata[]="Hel......
  • Linux命令(90)之cp
    linux命令之cp1.cp介绍linux命令cp是用来复制文件或目录2.cp用法cp[参数]scrdestcp常用参数参数说明-a保留文件的属性,进行递归复制,相当于-pdr-f强制复制,不提示3.实例3.1.复制1.txt文件至ztj目录命令:cp-a1.txtztj/[root@centos79-3~]#ls1.txt1.txt[root@centos79-3......
  • Linux命令(89)之xargs
    linux命令之xargs1.xargs介绍linux命令xargs是从标准输入(管道或stdin、输入重定向)获取数据,并将数据转换成命令行的参数简单理解就是find管道|后面接文件,就需要xargs。假如|前面输入的是文字、字符串就不需要接xargs2.xargs用法xargs[参数]xargs常用参数参数说明-n数字分组......
  • 11、Linux文件与目录权限
    Linux文件与目录权限目录Linux文件与目录权限一、Linux文件基本属性1、文件介绍2、Linux文件属主和属组二、更改文件属性1、chmod命令2、chown命令3、chgrp命令4、chattr命令5、lsattr命令三、其他1、权限掩码2、特殊权限①SBIT(粘滞位)②SUID(属主特殊权限)③SGID(属组特殊权限)3、fi......