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" 识别到,OpenSSL的ReadMe给的示例在/lib,大概是在构建OpenSSL时默认的configure指定了lib路径 // #define PKCS11_ENGINE_PATH "/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so" #define …...

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

【简单讲解下OneFlow深度学习框架】
🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…...

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

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

【PythonWeb开发】Flask自定义模板路径和静态资源路径
在大型的 Flask 项目中,确实可能会有多个子应用(Blueprints),每个子应用可能都有自己的静态文件和模板。为了更好地管理和组织这些资源,可以使用static_folder 和template_folder 属性来统一管理。必须同时设置好主应用…...

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

Does a vector database maintain pre-vector chunked data for RAG systems?
题意:一个向量数据库是否为RAG系统维护预向量化分块数据? 问题背景: 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 将错误分为两大类:可恢复的(recoverable)和 不可恢复的(unrecoverable)错误。对于一个可恢复的错误,比如文件未找到的错误,我们很可能只想向用户报告问题并重试操作。不可恢复的错误总是 b…...
自动化测试:使用Postman进行接口测试与脚本编写
Postman 是一种流行的 API 测试工具,广泛应用于开发和测试过程中。它不仅可以用于手动测试,还支持自动化测试和脚本编写,以确保 API 的可靠性和性能。本文将详细介绍如何使用 Postman 进行接口测试与脚本编写,帮助你更高效地进行自…...

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

基于大语言模型LangChain框架:知识库问答系统实践
ChatGPT 所取得的巨大成功,使得越来越多的开发者希望利用 OpenAI 提供的 API 或私有化模型开发基于大语言模型的应用程序。然而,即使大语言模型的调用相对简单,仍需要完成大量的定制开发工作,包括 API 集成、交互逻辑、数据存储等…...
解锁Transformer的鲁棒性:深入分析与实践指南
🛡️ 解锁Transformer的鲁棒性:深入分析与实践指南 Transformer模型自从由Vaswani等人在2017年提出以来,已经成为自然语言处理(NLP)领域的明星模型。然而,模型的鲁棒性——即模型在面对异常、恶意或不寻常…...

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

AI绘画 Stable Diffusion【实战进阶】:图片的创成式填充,竖图秒变横屏壁纸!想怎么扩就怎么扩!
大家好,我是向阳。 所谓图片的创成式填充,就是基于原有图片进行扩展或延展,在保证图片合理性的同时实现与原图片的高度契合。是目前图像处理中常见应用之一。之前大部分都是通过PS工具来处理的。今天我们来看看在AI绘画工具 Stable Diffusio…...
Linux内核 -- 汇编结合ko案例之PMU获取cpu cycle技术
ARMv7汇编实现周期计数读取与清空 本文档详细描述了如何在ARMv7平台上使用汇编语言编写周期计数器读取与清空函数,如何在内核模块中导出这些函数供其他模块调用,以及如何使用Netlink接口供用户态程序进行调用。 1. 汇编函数实现 首先,编写…...
探索 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
长城,是中华民族的一张重要名片,是中华民族坚韧不屈、自强不息的精神象征,被联合国教科文组织列入世界文化遗产名录。那么在古代,长城是如何以其复杂的防御体系,一次次抵御外族入侵,而这些防御体系又能给软…...
ISO 19110操作要求类中的/req/operation/formal-definition详细解释
/req/operation/formal-definition 要求: 每个要素操作实体必须具有一个形式定义(formal definition),该定义应明确描述操作的行为和影响。 具体解释 定义 要素操作实体(feature operation entity):这…...
豆包大语言模型API调用错误码一览表
本文介绍了您可能从 API 和官方 SDK 中看到的错误代码。 http code说明 400 原因:错误的请求,例如缺少必要参数,或者参数不符合规范等 解决方法:检查请求后重试 401 原因:认证错误,代表服务无法对请求进…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...