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

Linux 实现OpenSSL 服务器端客户端通信的更多相关文章

  1. twisted服务器端客户端通信(转载填坑)

    服务器端代码 # -*- coding:UTF-8 -*- from time import ctime from twisted.internet import reactor from twist ...

  2. MQ服务器端和客户端通信浅谈

    MQ服务器端和客户端通信浅谈 1. WebSphere MQ的服务端的安装和配置 (1)创建名为venus.queue.manager的默认队列管理器. 在DOS窗口命令提示符下,输入以下命令: cr ...

  3. Linux下OpenSSL的安装与使用

    Linux下OpenSSL的安装与使用 OpenSSL简介 OpenSSL是一个SSL协议的开源实现,采用C语言作为开发语言,具备了跨平台的能力,支持Unix/Linux.Windows.Mac OS ...

  4. C#调用接口注意要点 socket,模拟服务器、客户端通信 在ASP.NET Core中构建路由的5种方法

    C#调用接口注意要点   在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用, 所以首先需要通过调用登录接口来保存c ...

  5. JAVA基础知识之网络编程——-TCP/IP协议,socket通信,服务器客户端通信demo

    OSI模型分层 OSI模型是指国际标准化组织(ISO)提出的开放系统互连参考模型(Open System Interconnection Reference Model,OSI/RM),它将网络分为七 ...

  6. Linux下简单的socket通信实例

    Linux下简单的socket通信实例 If you spend too much time thinking about a thing, you’ll never get it done. —Br ...

  7. C#使用Socket实现一个socket服务器与多个socket客户端通信

    在分布式调度系统中,如果要实现调度服务器与多台计算节点服务器之间通信,采用socket来实现是一种实现方式,当然我们也可以通过数据存储任务,子节点来完成任务,但是往往使用数据作为任务存储都需要定制开发 ...

  8. 基于OpenSSL的HTTPS通信C++实现

      HTTPS是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL.Nebula是一个为开发者提供一个快速开发 ...

  9. Python_服务器与多客户端通信、UDP协议、pycharm打印带颜色输出、时间同步的机制

    1.服务器与多客户端通信 import socket # 创建tcp socket的套接字 sk = socket.socket() # bind sk.bind(('127.0.0.1',8080) ...

  10. C# Socket服务端与客户端通信(包含大文件的断点传输)

    步骤: 一.服务端的建立 1.服务端的项目建立以及页面布局 2.各功能按键的事件代码 1)传输类型说明以及全局变量 2)Socket通信服务端具体步骤:   (1)建立一个Socket   (2)接收 ...

随机推荐

  1. 9.24java wab实现创建新界面验证码

    <!DOCTYPE html> <html> <head> <title>User Login</title> <style> ...

  2. Flutter一些概念(一)

    1 简述Flutter是什么以及它的主要优势 Flutter是一种由Google开发的开源移动应用开发框架,可以用于构建高度定制化.美观并且性能卓越的移动应用程序,其主要优势有: 跨平台,一次编码,可 ...

  3. Windows 风格的个人网盘,支持OnlyOffice、支持音视频聊天、支持自动更新

    一年前,我开源了这个网盘,详见Windows风格的个人网盘,支持文档在线编辑,这一年期间,这个网盘进行了大量的更新,具体如下: 新增支持的功能如下: 支持 OnlyOffice (Word.Excel ...

  4. 第六章 (Nginx+Lua)Web开发实战HTTP服务

    此处我说的HTTP服务主要指如访问京东网站时我们看到的热门搜索.用户登录.实时价格.实时库存.服务支持.广告语等这种非Web页面,而是在Web页面中异步加载的相关数据.这些服务有个特点即访问量巨大.逻 ...

  5. Tomcat启用manager管理

    1.修改远程访问限制: 修改webapps/manager/META-INF/context.xml和webapps/host-manager/META-INF/context.xml,在<Co ...

  6. 深入理解第三范式(3NF):数据库设计中的重要性与实践

    title: 深入理解第三范式(3NF):数据库设计中的重要性与实践 date: 2025/1/17 updated: 2025/1/17 author: cmdragon excerpt: 在数据库 ...

  7. Svelte 最新中文文档翻译(5)—— 基础标记

    前言 Svelte,一个非常"有趣".用起来"很爽"的前端框架.从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 ...

  8. 深入理解Java泛型、协变逆变、泛型通配符、自限定

    禁止转载 重写了之前博客写的泛型相关内容,全部整合到这一篇文章里了,把坑都填了,后续不再纠结这些问题了.本文深度总结了函数式思想.泛型对在Java中的应用,解答了许多比较难的问题. 纯函数 协变 逆变 ...

  9. Windows中GNURadio的安装

    对于一个常常使用Python的人来讲(此处指我),conda环境是必不可少的,(Anaconda或Miniconda). 在Windows中且已经安装过conda环境的情况下,安装GNURadio特别 ...

  10. 帮您了解CDN节点如何做到访问加速与安全防护

    本文分享自天翼云开发者社区<帮您了解CDN节点如何做到访问加速与安全防护>,作者:尹****荷 网站业务痛点 在当前网站快速发展的背景下,网站业务突增往往伴随着一系列网络安全隐患.主要会有 ...