当前位置: 首页 > news >正文

TLS + OpenSSL + Engine + PKCS#11 + softhsm2 安全通信

引擎库路径只有在 /lib 下才能被 "LOAD" 识别到,OpenSSL的ReadMe给的示例在/lib,大概是在构建OpenSSL时默认的configure指定了lib路径

// #define PKCS11_ENGINE_PATH "/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so"
#define PKCS11_ENGINE_PATH "/lib/pkcs11.so"

本以为通过配置有效

./Configure --prefix=/usr/local/openssl \--openssldir=/usr/local/openssl

或者改Makefile有效,但是

old="ENGINESDIR=\$(libdir)\/engines-1.1"
new="ENGINESDIR=\/usr\/lib\/engine-1.1"
sed -i "s/$old/$new/g" Makefile

构建出来还是

# openssl engine pkcs11 -t
281473798283296:error:25066067:DSO support routines:dlfcn_load:could not load the shared library:crypto/dso/dso_dlfcn.c:118:filename(/home/test0923/Documents/optee_three_part/openssl/out/lib/engines-1.1/pkcs11.so): /home/test0923/Documents/optee_three_part/openssl/out/lib/engines-1.1/pkcs11.so: cannot open shared object file: No such file or directory
281473798283296:error:25070067:DSO support routines:DSO_load:could not load the shared library:crypto/dso/dso_lib.c:162:
281473798283296:error:260B6084:engine routines:dynamic_load:dso not found:crypto/engine/eng_dyn.c:434:
281473798283296:error:2606A074:engine routines:ENGINE_by_id:no such engine:crypto/engine/eng_list.c:421:id=pkcs11

但只找到了export方法

export OPENSSL_ENGINES=/usr/lib/engines-1.1

客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/err.h>
#include <openssl/engine.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>// #define PKCS11_ENGINE_PATH "/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so"
#define PKCS11_ENGINE_PATH "/lib/pkcs11.so"
#define PKCS11_MODULE_PATH "/usr/lib/softhsm/libsofthsm2.so"#define CERT_FILE "../hsm_pem/client.crt"
#define CA_CERT_FILE "../hsm_pem/ca.crt"#define TOKEN_LABEL "mytoken"
#define PIN "1234"
#define KEY_ID "mytoken"#define MAXBUF 1024void initialize_ssl_library() {SSL_library_init();SSL_load_error_strings();OpenSSL_add_all_algorithms();
}void cleanup_ssl_library() {EVP_cleanup();ERR_free_strings();
}ENGINE *load_pkcs11_engine() {ENGINE_load_dynamic();ENGINE *engine = ENGINE_by_id("dynamic");if (!engine) {fprintf(stderr, "Failed to load dynamic engine\n");return NULL;}if (!ENGINE_ctrl_cmd_string(engine, "SO_PATH", PKCS11_ENGINE_PATH, 0) ||!ENGINE_ctrl_cmd_string(engine, "ID", "pkcs11", 0) ||!ENGINE_ctrl_cmd_string(engine, "LIST_ADD", "1", 0) ||!ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0)) {fprintf(stderr, "Failed to configure and load PKCS#11 engine\n");ENGINE_free(engine);return NULL;}if (!ENGINE_ctrl_cmd_string(engine, "MODULE_PATH", PKCS11_MODULE_PATH, 0)) {fprintf(stderr, "Failed to set MODULE_PATH\n");ENGINE_free(engine);return NULL;}if (!ENGINE_init(engine)) {fprintf(stderr, "Failed to initialize PKCS#11 engine\n");ENGINE_free(engine);return NULL;}if (!ENGINE_ctrl_cmd_string(engine, "PIN", PIN, 0)) {fprintf(stderr, "Failed to set PIN\n");ENGINE_free(engine);return NULL;}return engine;
}int ShowCerts(SSL * ssl)
{X509 *cert;char *line;cert = SSL_get_peer_certificate(ssl);// SSL_get_verify_result()是重点,SSL_CTX_set_verify()只是配置启不启用并没有执行认证,调用该函数才会真证进行证书认证// 如果验证不通过,那么程序抛出异常中止连接if(SSL_get_verify_result(ssl) == X509_V_OK){printf("收到server X509证书\n");}else{printf("未收到server X509证书\n");return 1;}if (cert != NULL) {printf("server数字证书信息:\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\n", line);free(line);X509_free(cert);printf("对server证书验证通过!!!\n");} else{printf("无证书信息,对server证书验证失败!!!\n");return 1;}return 0;
}int main(int argc, char **argv)
{initialize_ssl_library();SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());if (!ctx) {fprintf(stderr, "Failed to create SSL_CTX\n");return 1;}// 双向验证// SSL_VERIFY_PEER---要求对证书进行认证,没有证书也会放行// SSL_VERIFY_FAIL_IF_NO_PEER_CERT---要求客户端需要提供证书,但验证发现单独使用没有证书也会放行SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);// Load CA certificateif (!SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, NULL)) {fprintf(stderr, "Failed to load CA certificate\n");SSL_CTX_free(ctx);cleanup_ssl_library();return 1;}// Load client certificateif (!SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM)) {fprintf(stderr, "Failed to load client certificate\n");SSL_CTX_free(ctx);cleanup_ssl_library();return 1;}// Load PKCS#11 engineENGINE *engine = load_pkcs11_engine();if (!engine) {SSL_CTX_free(ctx);cleanup_ssl_library();return 1;}char key_id[256];snprintf(key_id, sizeof(key_id), "pkcs11:token=%s;object=%s", TOKEN_LABEL, KEY_ID);EVP_PKEY *pkey = ENGINE_load_private_key(engine, key_id, NULL, NULL);if (!pkey) {fprintf(stderr, "Failed to load private key from PKCS#11\n");ENGINE_free(engine);SSL_CTX_free(ctx);cleanup_ssl_library();return 1;}if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {fprintf(stderr, "Failed to use private key\n");EVP_PKEY_free(pkey);ENGINE_free(engine);SSL_CTX_free(ctx);cleanup_ssl_library();return 1;}EVP_PKEY_free(pkey);ENGINE_free(engine);// Verify that the private key matches the certificateif (!SSL_CTX_check_private_key(ctx)) {fprintf(stderr, "Private key does not match the certificate public key\n");SSL_CTX_free(ctx);cleanup_ssl_library();return 1;}/* 创建一个 socket 用于 tcp 通信 */int sockfd;struct sockaddr_in dest;if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("Socket");exit(errno);}printf("socket created success!\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 success!\n");/* 连接服务器 */if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {perror("Connect ");exit(errno);}printf("server connected  success!\n");// Create SSL connectionSSL *ssl = SSL_new(ctx);if (!ssl) {fprintf(stderr, "Failed to create SSL object\n");SSL_CTX_free(ctx);cleanup_ssl_library();return 1;}SSL_set_fd(ssl, sockfd);// Perform SSL/TLS handshake with the serverif (SSL_connect(ssl) <= 0) {fprintf(stderr, "SSL/TLS handshake failed\n");SSL_free(ssl);SSL_CTX_free(ctx);cleanup_ssl_library();return 1;}printf("SSL/TLS handshake successful\n");ShowCerts(ssl);char send_buffer[MAXBUF + 1];char recv_buffer[MAXBUF + 1];int len;while(1){//使用SSL_write函数发送数据printf("请输入要发送给服务器的内容:\n");scanf("%s", send_buffer);if(!strncmp(send_buffer,"+++",3))break;     //收到+++表示退出/* 发消息给服务器 */len = SSL_write(ssl, send_buffer, strlen(send_buffer));if (len < 0)printf("消息'%s'发送失败!错误代码是%d, 错误信息是'%s'\n",send_buffer, errno, strerror(errno));elseprintf("消息'%s'发送成功,共发送了%d个字节! \n",send_buffer, len);memset(send_buffer,0,sizeof(send_buffer));/* 使用SSL_read函数接收数据,接收对方发过来的消息,最多接收 MAXBUF 个字节 */len = SSL_read(ssl, recv_buffer, MAXBUF);if (len > 0)printf("接收消息成功:'%s',共%d个字节的数据\n",recv_buffer, len);else {printf("消息接收失败!错误代码是%d, 错误信息是'%s'\n",errno, strerror(errno));break;}memset(recv_buffer,0,sizeof(recv_buffer));}SSL_free(ssl);SSL_CTX_free(ctx);cleanup_ssl_library();return 0;
}

使用参数

./ssl_server 7838 1 ./pem/server.crt ./pem/server.key ./pem/ca.crt
./ssl_client 127.0.0.1 7838

测试结果,服务端

./ssl_server 7838 1 ./pem/server.crt ./pem/server.key ./pem/ca.crt
socket created success!
binded success!
begin listen,waitting for client connect...
server: got connection from 127.0.0.1, port 35546, socket 6
收到client X509证书
client数字证书信息:
证书: /CN=localhost/C=CN/ST=clientprovince/L=clientcity/O=clientorganization/OU=clientgroup
颁发者: /CN=MyCA对client证书验证通过!!!等待客户端发送过来的消息:
接收client消息成功:'saddfsafijd',共11个字节的数据
请输入要发送给客户端的内容:
asfdsa
消息'asfdsa'发送成功,共发送了6个字节!
等待客户端发送过来的消息:

客户端

./ssl_client 127.0.0.1 7838
socket created success!
address created success!
server connected  success!
SSL/TLS handshake successful
收到server X509证书
server数字证书信息:
证书: /CN=myserver.com
颁发者: /CN=MyCA对server证书验证通过!!!请输入要发送给服务器的内容:
saddfsafijd
消息'saddfsafijd'发送成功,共发送了11个字节! 
接收消息成功:'asfdsa',共6个字节的数据
请输入要发送给服务器的内容:

 服务端引用

基于openssl实现https双向身份认证及安全通信_基于openssl身份认证-CSDN博客

相关文章:

TLS + OpenSSL + Engine + PKCS#11 + softhsm2 安全通信

引擎库路径只有在 /lib 下才能被 "LOAD" 识别到&#xff0c;OpenSSL的ReadMe给的示例在/lib&#xff0c;大概是在构建OpenSSL时默认的configure指定了lib路径 // #define PKCS11_ENGINE_PATH "/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so" #define …...

Unity实现简单的MVC架构

文章目录 前言MVC基本概念示例流程图效果预览后话 前言 在Unity中&#xff0c;MVC&#xff08;Model-View-Controller&#xff09;框架是一种架构模式&#xff0c;用于分离游戏的逻辑、数据和用户界面。MVC模式可以帮助开发者更好地管理代码结构&#xff0c;提高代码的可维护性…...

【简单讲解下OneFlow深度学习框架】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…...

FastGPT 调用Qwen 测试Hello world

Ubuntu 安装Qwen/FastGPT_fastgpt message: core.chat.chat api is error or u-CSDN博客 参考上面文档 安装FastGPT后 登录&#xff0c; 点击右上角的 新建 点击 这里&#xff0c;配置AI使用本地 ollama跑的qwen模型 问题&#xff1a;树上有3只鸟&#xff0c;开了一枪&#…...

Golang-GMP

GMP调度 golang-GMP语雀笔记整理 GMP调度设计目的&#xff0c;为何设计GMP?GMP的底层实现几个核心数据结构GMP调度流程 设计目的&#xff0c;为何设计GMP? 无论是多进程、多线程目的都是为了并发提高cpu的利用率&#xff0c;但多进程、多线程都存在局限性。比如多进程通过时…...

【PythonWeb开发】Flask自定义模板路径和静态资源路径

在大型的 Flask 项目中&#xff0c;确实可能会有多个子应用&#xff08;Blueprints&#xff09;&#xff0c;每个子应用可能都有自己的静态文件和模板。为了更好地管理和组织这些资源&#xff0c;可以使用static_folder 和template_folder 属性来统一管理。必须同时设置好主应用…...

Java对象创建过程

在日常开发中&#xff0c;我们常常需要创建对象&#xff0c;那么通过new关键字创建对象的执行中涉及到哪些流程呢&#xff1f;本文主要围绕这个问题来展开。 类的加载 创建对象时我们常常使用new关键字。如下 ObjectA o new ObjectA();对虚拟机来讲首先需要判断ObjectA类的…...

Does a vector database maintain pre-vector chunked data for RAG systems?

题意&#xff1a;一个向量数据库是否为RAG系统维护预向量化分块数据&#xff1f; 问题背景&#xff1a; I believe that when using an LLM with a Retrieval-Augmented Generation (RAG) approach, the results retrieved from a vector search must ultimately be presented…...

Rust-11-错误处理

Rust 将错误分为两大类&#xff1a;可恢复的&#xff08;recoverable&#xff09;和 不可恢复的&#xff08;unrecoverable&#xff09;错误。对于一个可恢复的错误&#xff0c;比如文件未找到的错误&#xff0c;我们很可能只想向用户报告问题并重试操作。不可恢复的错误总是 b…...

自动化测试:使用Postman进行接口测试与脚本编写

Postman 是一种流行的 API 测试工具&#xff0c;广泛应用于开发和测试过程中。它不仅可以用于手动测试&#xff0c;还支持自动化测试和脚本编写&#xff0c;以确保 API 的可靠性和性能。本文将详细介绍如何使用 Postman 进行接口测试与脚本编写&#xff0c;帮助你更高效地进行自…...

ONLYOFFICE 8.1 桌面编辑器测评:引领数字化办公新潮流

目录 前言 下载安装 新功能概述 1.PDF 编辑器的改进 2. 演示文稿中的幻灯片版式 3.语言支持的改进 4. 隐藏“连接到云”板块 5. 页面颜色设置和配色方案 界面设计&#xff1a;简洁大方&#xff0c;操作便捷 性能评测&#xff1a;稳定流畅&#xff0c;高效运行 办公环…...

基于大语言模型LangChain框架:知识库问答系统实践

ChatGPT 所取得的巨大成功&#xff0c;使得越来越多的开发者希望利用 OpenAI 提供的 API 或私有化模型开发基于大语言模型的应用程序。然而&#xff0c;即使大语言模型的调用相对简单&#xff0c;仍需要完成大量的定制开发工作&#xff0c;包括 API 集成、交互逻辑、数据存储等…...

解锁Transformer的鲁棒性:深入分析与实践指南

&#x1f6e1;️ 解锁Transformer的鲁棒性&#xff1a;深入分析与实践指南 Transformer模型自从由Vaswani等人在2017年提出以来&#xff0c;已经成为自然语言处理&#xff08;NLP&#xff09;领域的明星模型。然而&#xff0c;模型的鲁棒性——即模型在面对异常、恶意或不寻常…...

mybatis#号和$区别

在MyBatis中&#xff0c;#{}和${}都是用于实现动态SQL的占位符&#xff0c;但它们在使用场景和安全性上有明显的区别&#xff1a; 用途区别&#xff1a; #{}主要用于传递接口传输过来的具体数据&#xff0c;如参数值&#xff0c;它可以防止SQL注入&#xff0c;因为MyBatis会…...

AI绘画 Stable Diffusion【实战进阶】:图片的创成式填充,竖图秒变横屏壁纸!想怎么扩就怎么扩!

大家好&#xff0c;我是向阳。 所谓图片的创成式填充&#xff0c;就是基于原有图片进行扩展或延展&#xff0c;在保证图片合理性的同时实现与原图片的高度契合。是目前图像处理中常见应用之一。之前大部分都是通过PS工具来处理的。今天我们来看看在AI绘画工具 Stable Diffusio…...

Linux内核 -- 汇编结合ko案例之PMU获取cpu cycle技术

ARMv7汇编实现周期计数读取与清空 本文档详细描述了如何在ARMv7平台上使用汇编语言编写周期计数器读取与清空函数&#xff0c;如何在内核模块中导出这些函数供其他模块调用&#xff0c;以及如何使用Netlink接口供用户态程序进行调用。 1. 汇编函数实现 首先&#xff0c;编写…...

探索 Symfony 框架:工作原理、特点及技术选型

目录 1. 概述 2. Symfony 的工作原理 2.1 MVC 架构 2.2 前端控制器模式 2.3 路由机制 2.4 依赖注入容器 2.5 事件驱动架构 3. Symfony 的特点 3.1 高度可扩展性 3.2 强大的社区支持和生态系统 3.3 优秀的性能和可伸缩性 3.4 严格的代码规范和最佳实践 4. Symfony …...

从万里长城防御体系看软件安全体系建设@安全历史03

长城&#xff0c;是中华民族的一张重要名片&#xff0c;是中华民族坚韧不屈、自强不息的精神象征&#xff0c;被联合国教科文组织列入世界文化遗产名录。那么在古代&#xff0c;长城是如何以其复杂的防御体系&#xff0c;一次次抵御外族入侵&#xff0c;而这些防御体系又能给软…...

ISO 19110操作要求类中的/req/operation/formal-definition详细解释

/req/operation/formal-definition 要求: 每个要素操作实体必须具有一个形式定义&#xff08;formal definition&#xff09;&#xff0c;该定义应明确描述操作的行为和影响。 具体解释 定义 要素操作实体&#xff08;feature operation entity&#xff09;&#xff1a;这…...

豆包大语言模型API调用错误码一览表

本文介绍了您可能从 API 和官方 SDK 中看到的错误代码。 http code说明 400 原因&#xff1a;错误的请求&#xff0c;例如缺少必要参数&#xff0c;或者参数不符合规范等 解决方法&#xff1a;检查请求后重试 401 原因&#xff1a;认证错误&#xff0c;代表服务无法对请求进…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...