基于openssl实现TCP双向认证

文章参考

深入探索 OpenSSL:概念、原理、开发步骤、使用方法、使用场景及代码示例
c++使用OpenSSL基于socket实现tcp双向认证ssl(使用TSL协议)代码实现
SSL握手通信详解及linux下c/c++ SSL Socket代码举例(另附SSL双向认证客户端代码)
SSL/CA 证书及其相关证书文件(pem、crt、cer、key、csr)

TCP实现OpenSSL原理(TCP3次握手+OPENSLL四次握手

SSL全称安全套接字协议层,为了通信安全,使用RSA非对称加密交换密钥,密钥交换完成后使用对称密钥进行通信。(为什么将非对称加密切换称对称加密是为了提供通信效率。非对称加密效率低)
TCP openssl双向认证:即在TCP三次握手的基础上增加一次openssl的4次握手。

实现OPENSSL四次握手
  1. 服务端,在已建立的TCP链接基础上调用SSL_accept
  2. 客户端,在已建立的TCP链接基础上调用SSL_connect
TCP SSL 服务端步骤
  1. 初始化ssl并加载证书和密钥
  2. TCP服务收到客户端连接之后调用SSL_accept进行四次握手
  3. SSL握手建立完成之后调用SSL_readSSL_write收发数据
  4. 使用完成之后关闭并释放SSL资源SSL_shutdownSSL_free
#include <iostream>
#include <tchar.h>
#include <winsock.h>
#include "openssl/ssl.h"#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"libcrypto_static.lib")
#pragma comment(lib,"libssl_static.lib")using namespace std;int main()
{WSADATA wsdata;int errcode = WSAStartup(MAKEWORD(2, 2), &wsdata);if (errcode != 0){std::cout << "WSAStartup failed,errcode:%d" << errcode<<std::endl;return 0;}//初始化sslSSL_library_init();//加载ssl算法库OpenSSL_add_all_algorithms();//加载ssl 错误信息SSL_load_error_strings();//以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL ContextSSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_server_method());if (ssl_ctx == nullptr){std::cout << "SSL_CTX_new failed"<<std::endl;return 0;}//加载数字证书if (SSL_CTX_use_certificate_chain_file(ssl_ctx, "ca.crt") <= 0){printf("SSL_CTX_use_certificate_chain_file failed\r\n");return 0;}//加载私钥if (SSL_CTX_use_PrivateKey_file(ssl_ctx, "ca.key", SSL_FILETYPE_PEM) <= 0){printf("SSL_CTX_use_PrivateKey_file failed\r\n");return 0;}// 检查用户私钥是否正确 if (!SSL_CTX_check_private_key(ssl_ctx)){printf("SSL_CTX_check_private_key failed\r\n");return 0;}SSL_CTX_set_timeout(ssl_ctx, 100);//创建socket->bind->list->acceptSOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0);if (listen_sock == INVALID_SOCKET){printf("socket create failed\r\n");return 0;}//setsocketopt resuse portunsigned short port = 32100;sockaddr_in sin;memset(&sin, 0, sizeof(sin));sin.sin_family = AF_INET;sin.sin_port = htons(port);sin.sin_addr.S_un.S_addr = INADDR_ANY;if (SOCKET_ERROR == bind(listen_sock, (sockaddr*)&sin, sizeof(sin))){printf("socket bind failed\r\n");return 0;}if (SOCKET_ERROR == listen(listen_sock, 5)){printf("socket listen failed\r\n");return 0;}printf("tcp ssl server:%d\r\n", port);while (true){char szbuf[1024] = "";sockaddr_in peer_addr;int naddr_len = sizeof(peer_addr);printf("wait client...\r\n");SOCKET soct_peer = accept(listen_sock, (sockaddr*)&peer_addr, &naddr_len);printf("accept client ,socket:%d\r\n", soct_peer);//将socket和ssl绑定(ssl握手)SSL* ssl_peer = SSL_new(ssl_ctx);if (ssl_peer == nullptr){printf("socket:%d,SSL_new failed\r\n", soct_peer);goto freessl;}SSL_set_fd(ssl_peer, soct_peer);//这里会无限阻塞,为了安全应该异步增加一个超时值,如果超时仍然未连接上则应该closeif (SSL_accept(ssl_peer) < 0){printf("socket:%d,SSL_accept failed\r\n", soct_peer);goto freessl;}//开始ssl读写SSL_read(ssl_peer, szbuf, 1024);printf("socket[%d] read:%s\r\n", soct_peer, szbuf);SSL_write(ssl_peer, szbuf, lstrlenA(szbuf));freessl:shutdown(soct_peer, 0);closesocket(soct_peer);//释放sslif(ssl_peer)SSL_free(ssl_peer);continue;}return 0;
}
TCP SSL 客户端端步骤
  1. TCP客户端连接成功之后调用SSL_connect进行四次握手
  2. SSL握手建立完成之后调用SSL_readSSL_write收发数据
  3. 使用完成之后关闭并释放SSL资源SSL_shutdownSSL_free
#include <iostream>
#include <tchar.h>
#include <winsock.h>
#include "openssl/ssl.h"#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"libcrypto_static.lib")
#pragma comment(lib,"libssl_static.lib")using namespace std;int main()
{WSADATA wsdata;int errcode = WSAStartup(MAKEWORD(2, 2), &wsdata);if (errcode != 0){std::cout << "WSAStartup failed,errcode:%d" << errcode << std::endl;return 0;}//初始化sslSSL_library_init();//加载ssl算法库OpenSSL_add_all_algorithms();//加载ssl 错误信息SSL_load_error_strings();//以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL ContextSSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method());if (ssl_ctx == nullptr){std::cout << "SSL_CTX_new failed" << std::endl;return 0;}//SSL_CTX_set_timeout(ssl_ctx, 100);//创建socket->connectSOCKET cli_sock = socket(AF_INET, SOCK_STREAM, 0);if (cli_sock == INVALID_SOCKET){printf("socket create failed\r\n");return 0;}//setsocketopt resuse portsockaddr_in sin;memset(&sin, 0, sizeof(sin));sin.sin_family = AF_INET;sin.sin_port = htons(32100);sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");if (SOCKET_ERROR == connect(cli_sock, (sockaddr*)&sin, sizeof(sin))){printf("socket connect failed\r\n");return 0;}printf("connect client ,socket:%d\r\n", cli_sock);//将socket和ssl绑定(ssl握手)char szbuf[1024] = "Hellow word!!!";SSL* ssl_peer = SSL_new(ssl_ctx);if (ssl_peer == nullptr){printf("socket:%d,SSL_new failed\r\n", cli_sock);goto freessl;}SSL_set_fd(ssl_peer, cli_sock);//这里会无限阻塞,为了安全应该异步增加一个超时值,如果超时仍然未连接上则应该closeif (SSL_connect(ssl_peer) < 0){printf("socket:%d,SSL_accept failed\r\n", cli_sock);goto freessl;}printf("ssl connectd ok\r\n");SSL_write(ssl_peer, szbuf, lstrlenA(szbuf));//开始ssl读写memset(szbuf, 0, 1024);SSL_read(ssl_peer, szbuf, 1024);printf("socket[%d] read:%s\r\n", cli_sock, szbuf);
freessl:shutdown(cli_sock, 0);closesocket(cli_sock);//释放sslif (ssl_peer)SSL_free(ssl_peer);return 0;
}
NOTE

1. 服务端和客户端初始化SSL_CTX参数不同

//以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Context//客户端调用openssl客户端的方法
SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method());//服务端调用openssl服务端的方法
SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_server_method());

2. SSL_acceptSSL_connect阻塞函数
在同步调用 SSL_acceptSSL_connect的时候会进行阻塞,需要定时检测是否超时,如果超时则关闭当前socket,防止恶意链接。例如拿非openssl的客户端连接openssl的服务端,此时不会存在四次握手,在未发送数据前会一直阻塞下去,等待握手的完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/819349.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 Rust 和 DDD 构建 API 服务器

Introduction 介绍 I tried implementing an API server using Rust and the Axum framework. 我尝试使用 Rust 和 Axum 框架实现 API 服务器。 Target Audience 本文受众 Those who want to implement an API server with Rust. 那些想要用 Rust 实现 API 服务器的人。Those w…

如何查看docker配置的镜像仓库

在Docker中&#xff0c;想要查看配置的镜像仓库&#xff08;注册表&#xff09;地址&#xff0c;可以通过查询Docker守护进程的配置来实现。在Linux系统中&#xff0c;Docker守护进程的配置文件通常位于 /etc/docker/daemon.json。该文件中可能会包含registry-mirrors配置项&am…

【Delphi 爬虫库 2】使用封装好的 JSON 解析库对 JSON 数据进行解析

当我们使用GET或POST方法获取到JSON数据时&#xff0c;我们需要对其进行解析。倘若我们使用现有的JSON解析库&#xff0c;这一过程将变得异常简单。在前文中&#xff0c;我们获得了一个翻译结果的JSON数据&#xff0c;具体如下所示 {“sessionUuid”:“translate_uuid171308666…

贪心算法先导

贪心算法其实就是没有什么规律可言&#xff0c;所以大家了解贪心算法 就了解它没有规律的本质就够了。 不用花心思去研究其规律&#xff0c; 没有思路就立刻看题解。 基本贪心的题目 有两个极端&#xff0c;要不就是特简单&#xff0c;要不就是死活想不出来。 学完贪心之后再…

算法训练营第41天|LeetCode 343.整数拆分 96.不同的二叉搜索树

LeetCode 343.整数拆分 题目链接&#xff1a; LeetCode 343.整数拆分 解题思路&#xff1a; 递推公式&#xff1a;一个数n是由1到n-1和另一个数的分解而来的&#xff0c;而另一个数是由更小的数分解而来的。 代码&#xff1a; class Solution { public:int integerBreak(…

Springboot+Vue项目-基于Java+MySQL的校园周边美食探索及分享平台系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

SU-03T语音识别

语音识别的由SU-03T、咪头、喇叭、还有一个CH340串口组成。SU-03T不需要代码的写入&#xff0c;直接可以进行配置就可以使用&#xff0c;极大降低了开发难度。 为客户提供超低成本的离线语 音识别方案&#xff0c;可广泛且快速应用于智能家居&#xff0c;各类智能小家电&#x…

【BlueDroid】【BLE】开关广播\扫描\配对\连接分析

1. 精讲蓝牙协议栈&#xff08;Bluetooth Stack&#xff09;&#xff1a;SPP/A2DP/AVRCP/HFP/PBAP/IAP2/HID/MAP/OPP/PAN/GATTC/GATTS/HOGP等协议理论 2. 欢迎大家关注和订阅&#xff0c;【精讲蓝牙协议栈】和【Android Bluetooth Stack】专栏会持续更新中.....敬请期待&#x…

如何实现YOLOv8保存目标检测后的视频文件

首先安装所需的库和依赖项&#xff0c;确保你已经安装了OpenCV和YOLOv8的相关库和依赖项。你可以使用pip或conda来安装它们。 其次加载YOLOv8模型&#xff0c;使用YOLOv8的训练权重文件和配置文件&#xff0c;加载模型并进行初始化。这可以通过使用适当的库函数来完成&…

Java面试题:描述Java 17中的密封接口及其用途

Java 17是继Java 11和Java 16之后的又一个长期支持&#xff08;LTS&#xff09;版本&#xff0c;它于2021年9月发布。在Java 17中&#xff0c;一个重要的新特性是密封接口&#xff08;Sealed Interfaces&#xff09;&#xff0c;这是对Java接口的增强&#xff0c;它允许接口有更…

【Git】Git的安装与常用命令

Git的安装与常用命令 一、Git的安装 &#xff08;一&#xff09;下载 官网下载&#xff1a;https://git-scm.com/downloads 镜像网站&#xff1a;https://registry.npmmirror.com/binary.html?pathgit-for-windows/ &#xff08;二&#xff09;安装 双击安装&#xff0c…

Elasticsearch分布式搜索

实用篇-ES-环境搭建 ES是elasticsearch的简称。我在SpringBoot学习 数据层解决方案 的时候&#xff0c;写过一次ES笔记&#xff0c;可以结合一起看一下。 之前在SpringBoot里面写的相关ES笔记是基于Windows的&#xff0c;现在我们是基于docker容器来使用&#xff0c;需要你们提…

安装jmeter和ant

安装jmeter和ant 安装java环境 安装jdk和jre 下载Java SE Development Kit 8 Java SE subscribers will receive JDK 8 updates until at least December 2030. 选择指定包进行安装&#xff0c;如windows 共享账号参考&#xff1a;Oracle官网 账号及密码 目前官网下载低…

springboot接口提高查询速度方法

接口想要提高查询速度&#xff0c;需要减少查询数据库的次数&#xff0c;需要把循环里面的查询提出来一次性查询完毕&#xff0c;然后通过java代码来获取响应的值。如下所示&#xff1a; List<OrderInfoHtVO> orderInfoList orderInfoService.getOrderInfoHtlist(query…

K12智慧校园-学工中心

1 系统概述 学工管理系统用于帮助学校学工部门负责拟定学院年度学生工作计划&#xff0c;提出年度学生工作思路及工作要点&#xff0c;并负责指导各系开展学生工作&#xff1b;负责学院的学风建设与校园文明督查&#xff1b;负责新生军训工作的组织、协调和安排&#xff1b;负…

顺序表 (头删 尾删 清空)

//头删 | 1 #include "head.h" | 1 #ifndef ww87 void head_del(p lp) | 2 int main(int argc, const char *argv[]) …

js纯前端实现语音播报,朗读功能(2024-04-15)

实现语音播报要有两个原生API 分别是【window.speechSynthesis】【SpeechSynthesisUtterance】 项目代码 // 执行函数 initVoice({text: 项目介绍,vol: 1,rate: 1 })// 函数 export function initVoice(config) {window.speechSynthesis.cancel();//播报前建议调用取消的函数…

[阅读笔记2][FLAN]FINETUNED LANGUAGE MODELS ARE ZERO-SHOT LEARNERS

接下来这篇是谷歌的FLAN&#xff0c;提出了指令微调这一新范式&#xff0c;在2022年发表。 这篇论文指出GPT3的zero-shot性能相比few-shot性能差太多了。他们发现如果对预训练模型进行指令微调能使zero-shot性能显著提升&#xff0c;下面右图显示指令微调后zero-shot比GPT3 few…

【zml】vp9 vp8

目录 问题 方案 知识点 研究过程 源码编译的可能 问题 所有 的机型 中&#xff0c;就海思芯片的有这个问题。应该是它的h264的编解码 问题&#xff0c;所以目前是让它以vp9在推流就没有问题。 但zlm对于vp9的录相是没有实现的。 所以目前现状是海思芯片的&#xff0c;就…

Ubuntu 22.04安装中文输入法

1. 安装 sudo apt install fcitx5 2. 管理已安装的语言 Setting->Region & Language->Manage Installed Language 在下图中点击“安装”&#xff0c;之后需要等一会 选择Fcitx 5 3. 添加输入法 Setting->Keyboard 点击chinese 选择你想要的输入法 重启一下&a…