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

openssl3.2 - exp - 内存操作(建立,写入,读取)配置

文章目录

    • openssl3.2 - exp - 内存操作(建立,写入,读取)配置
    • 概述
    • 笔记
    • 调试细节
    • 运行效果
    • 测试工程实现
    • main.cpp
    • CMyOsslConfig.h
    • CMyOsslConfig.cpp
    • END

openssl3.2 - exp - 内存操作(建立,写入,读取)配置

概述

我的应用的配置文件是落地加密的, 无法直接用openssl配置接口载入读取.
应用先将加密的配置文件解密(openssl官方给的demo工程中有对文件的加解密例子).
从明文buffer中载入配置, 然后就可以用openssl的配置接口(BIO为入参)读取配置项的值.
做了实验, 用了1天搞定了. 封装了一个配置类. 可以在内存中建立配置, 写入配置, 读取配置.
在内存中建立配置,写入配置在服务端用.
客户端只用在内存中读取配置的接口.

笔记

调试细节

  • NCONF_load_bio()执行后, 会将输入的BIO内容清掉.
  • BIO_read()执行后, 如果后续不是要继续读取, 需要将数据读指针位置复原 BIO_seek(bio, 0)
  • 如无必要, 不要调用BIO_seek(). 查了openssl实现, 官方用法全部是BIO_seek(bio, 0).
  • 官方配置操作接口, 只有读取的接口. 因为官方用法, 都是用户自己手工编辑配置文件, openssl只需要读配置. 如果需要写配置内容, 需要自己封装(write buffer => BIO => CONF). 如果想自己确认写入BIO的内容是否正确, 可以将BIO写到文件来确认.

运行效果

[cpt_info] win_ver = win10
[cpt_info] ram = 32GB
[cfg_info] sec_cnt = 2
free mem_hook map, g_mem_hook_map.size() = 0, no openssl API call memory leak

测试工程实现

main.cpp

/*!
* \file main.cpp
*/#include "my_openSSL_lib.h"
#include <openssl/crypto.h>
#include <openssl/bio.h>#include <openssl/conf.h> // for CONF#include "CMyOsslConfig.h"#include <stdlib.h>
#include <stdio.h>
#include <assert.h>#include "CMemHookRec.h"void my_openssl_app();int main(int argc, char** argv)
{setvbuf(stdout, NULL, _IONBF, 0); // 清掉stdout缓存, 防止调用printf时阻塞mem_hook();my_openssl_app();mem_unhook();/*! run result[cpt_info] win_ver = win10[cpt_info] ram = 32GB[cfg_info] sec_cnt = 2free mem_hook map, g_mem_hook_map.size() = 0, no openssl API call memory leak*/return 0;
}void my_openssl_app()
{CONF* conf = NULL;STACK_OF(CONF_VALUE)* sk_of_conf_value = NULL;CONF_VALUE* conf_value = NULL;CMyOsslConfig _cfg;bool b_rc = false;const char* pszVal = NULL;do {// case - wirte new config to BIO/CONFb_rc = _cfg.init(); // !!assert(b_rc);_cfg.add_config_section("cpt_info");_cfg.add_config_item_after_section("win_ver", "win10");_cfg.add_config_item_after_section("ram", "32GB");_cfg.add_config_section("cfg_info");_cfg.add_config_item_after_section("sec_cnt", "2");// 如果要将_cfg中的BIO中的东西写入文件测试(方便人工观察配置文件是否写错?), 必须要在_cfg.updateConfig()之前, 否则BIO中的东西被NCONF_load_bio()载入后清掉了// _cfg.to_file("test.cfg"); // only for test// when add config content, need update(bio to CONF)_cfg.updateConfig(); // !!// 经过_cfg.updateConfig()后, _cfg中的BIO就空了, 如果要更新配置, 就需要重新写BIO// get cofig value from CONF* inside on CMyOsslConfigpszVal = _cfg.get_conf_item_value("cpt_info", "win_ver");if (NULL != pszVal){printf("[cpt_info] win_ver = %s\n", pszVal);}pszVal = _cfg.get_conf_item_value("cpt_info", "ram");if (NULL != pszVal){printf("[cpt_info] ram = %s\n", pszVal);}pszVal = _cfg.get_conf_item_value("cfg_info", "sec_cnt");if (NULL != pszVal){printf("[cfg_info] sec_cnt = %s\n", pszVal);}} while (false);
}

CMyOsslConfig.h

//! \file CMyOsslConfig.h#ifndef __CMYOSSLCONFIG_H__
#define __CMYOSSLCONFIG_H__#include <openssl/bio.h>
#include <openssl/conf.h> // for CONFclass CMyOsslConfig
{
public:CMyOsslConfig();virtual ~CMyOsslConfig();bool init();bool add_config_section(const char* pszIn);bool add_config_item_after_section(const char* pszItemName, const char* pszItemContent);bool updateConfig();BIO* get_bio();char* get_conf_item_value(const char* group, const char* name);bool to_file(const char* psz_file_pathname); // for test onlyprivate:bool append_to_bio(uint8_t* pBuf, int lenBuf);size_t bio_get_length(BIO* bio);bool bio_to_buf(BIO* bio, uint8_t*& pBuf, int& lenBuf);private:BIO* m_bio;CONF* m_conf;
};#endif // #ifndef __CMYOSSLCONFIG_H__

CMyOsslConfig.cpp

//! \file CMyOsslConfig.cpp#include "CMyOsslConfig.h"
#include <string.h>
#include <openssl/err.h>
#include <cassert>CMyOsslConfig::CMyOsslConfig():m_bio(NULL),m_conf(NULL)
{}CMyOsslConfig::~CMyOsslConfig()
{if (NULL != m_bio){BIO_free(m_bio);m_bio = NULL;}if (NULL != m_conf){NCONF_free(m_conf);m_conf = NULL;}
}bool CMyOsslConfig::init()
{bool b_rc = false;do {if (NULL == m_bio){m_bio = BIO_new(BIO_s_mem());if (NULL == m_bio){break;}}if (NULL == m_conf){m_conf = NCONF_new_ex(OSSL_LIB_CTX_get0_global_default(), NULL);if (NULL == m_conf){break;}}b_rc = true;} while (false);return b_rc;
}bool CMyOsslConfig::add_config_section(const char* pszIn)
{bool b_rc = false;char szBuf[1024];int len = 0;do {if (NULL == pszIn){break;}len = strlen(pszIn);if (len > (sizeof(szBuf) - 0x10)){break;}sprintf(szBuf, "[ %s ]\n", pszIn);if (NULL == m_bio){break;}if (!append_to_bio((uint8_t*)szBuf, strlen(szBuf))){break;}b_rc = true;} while (false);return b_rc;
}bool CMyOsslConfig::add_config_item_after_section(const char* pszItemName, const char* pszItemContent)
{bool b_rc = false;char szBuf[1024];int len = 0;do {if ((NULL == pszItemName) || (NULL == pszItemContent)){break;}len = (strlen(pszItemName) + strlen(pszItemContent));if (len > (sizeof(szBuf) - 0x10)){break;}sprintf(szBuf, "%s = %s\n", pszItemName, pszItemContent);if (NULL == m_bio){break;}if (!append_to_bio((uint8_t*)szBuf, strlen(szBuf))){break;}b_rc = true;} while (false);return b_rc;
}bool CMyOsslConfig::append_to_bio(uint8_t* pBuf, int lenBuf)
{bool b_rc = false;int len = 0;size_t szLen = 0;int bio_len_before = 0;int bio_len_after = 0;do {if ((NULL == pBuf) || (lenBuf <= 0)){break;}if (NULL == m_bio){break;}// szLen = bio_get_length(m_bio);// BIO_seek(m_bio, szLen);bio_len_before = bio_get_length(m_bio);len = BIO_write(m_bio, pBuf, lenBuf);bio_len_after = bio_get_length(m_bio);if (len != lenBuf){break;}if (len != (bio_len_after - bio_len_before)){break;}b_rc = true;} while (false);return b_rc;}BIO* CMyOsslConfig::get_bio()
{if (NULL != m_bio){// BIO_seek(m_bio, 0);}return m_bio;
}size_t CMyOsslConfig::bio_get_length(BIO* bio)
{size_t bio_length = 0;do {if (NULL == bio){break;}// BIO_seek(bio, 0);bio_length = BIO_ctrl_pending(bio);} while (false);return bio_length;
}bool CMyOsslConfig::updateConfig()
{bool b_rc = false;int i_rc = 0;long lineSn = 0;int len1 = 0;int len2 = 0;do {if ((NULL == m_bio) || (NULL == m_conf)){break;}// BIO_seek(m_bio, 0);// len1 = this->bio_get_length(m_bio);i_rc = NCONF_load_bio(m_conf, m_bio, &lineSn);// len2 = this->bio_get_length(m_bio);// m_bio有东西有数据长度, 但是经过NCONF_load_bio()后, m_conf里面有东西了, 但是m_bio的东西没了// 所以, 经过NCONF_load_bio后(), 就得当m_bio是空的来处理.// 如果是向m_bio中写东西, 然后写配置.// 如果要更新m_bio中的配置内容, 就必须重新写.if (i_rc <= 0){break;}b_rc = true;} while (false);return b_rc;
}char* CMyOsslConfig::get_conf_item_value(const char* group, const char* name)
{char* res = NULL;int i_rc = 0;do {if (NULL == m_conf){break;}res = NCONF_get_string(m_conf, group, name);if (NULL == res){ERR_pop_to_mark();}else {ERR_clear_last_mark();}} while (false);return res;
}bool CMyOsslConfig::to_file(const char* psz_file_pathname)
{bool b_rc = false;FILE* pf = NULL;uint8_t* pBuf = NULL;int len = 0;size_t sz_rc = 0;do {if (NULL == psz_file_pathname){break;}pf = fopen(psz_file_pathname, "wb");if (NULL == pf){break;}if (!bio_to_buf(get_bio(), pBuf, len)){break;}if ((NULL == pBuf) || (len <= 0)){break;}sz_rc = fwrite(pBuf, sizeof(char), len, pf);assert(sz_rc == len);b_rc = true;} while (false);if (NULL != pf){fclose(pf);pf = NULL;}if (NULL != pBuf){OPENSSL_free(pBuf);pBuf = NULL;}return b_rc;
}bool CMyOsslConfig::bio_to_buf(BIO* bio, uint8_t*& pBuf, int& lenBuf)
{bool b_rc = false;int i_rc = 0;do {if (NULL == bio){break;}lenBuf = bio_get_length(bio);pBuf = (uint8_t*)OPENSSL_malloc(lenBuf + 1);if (NULL == pBuf){break;}pBuf[lenBuf] = '\0';i_rc = BIO_read(bio, pBuf, lenBuf);BIO_seek(bio, 0); // ! 读完了, 将数据读指针恢复.b_rc = (i_rc == lenBuf);} while (false);return b_rc;
}

END

相关文章:

openssl3.2 - exp - 内存操作(建立,写入,读取)配置

文章目录 openssl3.2 - exp - 内存操作(建立,写入,读取)配置概述笔记调试细节运行效果测试工程实现main.cppCMyOsslConfig.hCMyOsslConfig.cppEND openssl3.2 - exp - 内存操作(建立,写入,读取)配置 概述 我的应用的配置文件是落地加密的, 无法直接用openssl配置接口载入读取…...

前端食堂技术周刊第 114 期:Interop 2024、TS 5.4 RC、2 月登陆浏览器的新功能、JSR、AI SDK 3.0

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;凉拌鸡架 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 大家好&#xff0c;我是童欧巴。欢迎来到前端食堂技术周刊&#xff0c;我们先来看下…...

#QT(信号与槽)

1.IDE&#xff1a;QTCreator 2.实验:自动添加槽函数&#xff0c;手动添加槽函数 3.记录 &#xff08;1&#xff09;自动添加 a.拖拽widget.ui&#xff0c;放置push-button组件&#xff0c;并且自动生成槽函数 b.发现widget.cpp和widget.h中出现添加的槽函数&#xff0c;注意w…...

go 设置滚动日志

方案 通过 log/slog 实现结构化日志生成&#xff0c;这是go1.21中推出的新特性&#xff1b;通过 lumberjack 实现日志文件分割。 示例 package mainimport ("gopkg.in/natefinch/lumberjack.v2""log/slog""os""path/filepath" )fun…...

Rollup入门学习:前端开发的构建利器

在前端开发领域&#xff0c;构建工具对于优化项目结构和提升代码效率扮演着至关重要的角色。Rollup作为一款轻量级且功能强大的JavaScript模块打包器&#xff0c;近年来备受开发者青睐。本文将带你走进Rollup的世界&#xff0c;帮助你快速入门并掌握其核心用法。 一、Rollup简介…...

游戏寻路之A*算法(GUI演示)

一、A*算法介绍 A*算法是一种路径搜索算法,用于在图形网络中找到最短路径。它结合了Dijkstra算法和启发式搜索的思想,通过综合利用已知的最短路径和估计的最短路径来优化搜索过程。在游戏自动寻路得到广泛应用。 二、A*算法的基本思想 在图形网络中选择一个起点和终点。维护…...

软件工程顶会——ICSE '24 论文清单、摘要

1、A Comprehensive Study of Learning-based Android Malware Detectors under Challenging Environments 近年来&#xff0c;学习型Android恶意软件检测器不断增多。这些检测器可以分为三种类型&#xff1a;基于字符串、基于图像和基于图形。它们大多在理想情况下取得了良好的…...

Vue点击复制到剪切板

一、Vue2写法 安装 &#xff08;官网地址&#xff09; npm install --save vue-clipboard2 使用 //main.js import VueClipboard from vue-clipboard2 Vue.use(VueClipboard)//页面使用 <button type"button"v-clipboard:copy"message"v-clipboard:su…...

链路负载均衡之DNS透明代理

一、DNS透明代理 一般来说&#xff0c;企业的客户端上都只能配置一个运营商的DNS服务器地址&#xff0c;DNS服务器通常会将域名解析成自己所在ISP内的Web服务器地址&#xff0c;这将导致内网用户的上网流量都集中在一个ISP的链路上转发&#xff0c;最终可能会造成链路拥塞&…...

2024大语言模型LLM基础|语义搜索Semantic_Search全解

目录 语义搜索Semantic_Search代码详解 为甚麽用Pinecone做向量索引&#xff1f;优点是什么&#xff1f; 有哪些常见向量索引方法&#xff1f; Pinecone做向量索引怎么用&#xff1f; 向量索引全解&#xff1a;含原理解析&#xff1a; 语义搜索Semantic_Search代码详解 1…...

vue中使用echarts实现人体动态图

最近一直处于开发大屏的项目&#xff0c;在开发中遇到了一个小知识点&#xff0c;在大屏中如何实现人体动态图。然后看了下echarts官方文档&#xff0c;根据文档中的示例调整出来自己想要的效果。 根据文档上发现 series 中 type 类型设置为 象形柱形图&#xff0c;象形柱图是…...

结构化思维助力Prompt创作:专业化技术讲解和实践案例

结构化思维助力Prompt创作&#xff1a;专业化技术讲解和实践案例 最早接触 Prompt engineering 时, 学到的 Prompt 技巧都是: 你是一个 XX 角色… 你是一个有着 X 年经验的 XX 角色… 你会 XX, 不要 YY.. 对于你不会的东西, 不要瞎说!…对比什么技巧都不用, 直接像使用搜索引…...

【0272】postgres内核分配 MyBackendId 实现原理(MyBackendId、MyProc、shmInvalBuffer)(三)

相关文章: 【0255】揭晓pg内核中MyBackendId的分配机制(后端进程Id,BackendId)(一) 【0256】揭晓pg内核中MyBackendId的分配机制(后端进程Id,BackendId)(二) 第一个backend process前,shmInvalBuffer的值情况 (gdb) p *shmInvalBuffer $153 = {minMsgNum =...

AUKFUKF的MATLAB程序,含源码

adaptive UKF与UKF效果对比 只有一个m文件,直接拖到MATLAB上面就能运行并输出结果了 部分结果 程序源码 % adaptive UKF与UKF效果对比 % author:Evand % 作者联系方式:evandjiang@qq.com(除前期达成一致外,付费咨询) % date: 2023-11-07 % Ver1 clear;clc;close all; %%…...

STM32(13)串口

串口的数据帧 1.空闲 2.起始位 3.数据位 4.校验位&#xff08;可有可无&#xff09; 为了验证数据传输是否出错而设立的比特位 1和4传输方式比较常见 校验规则&#xff1a; 根据1的个数&#xff0c;校验位会自己补0或1 5.停止位 例子&#xff1a; 同步通信 异步通信 波特率 …...

Element(Java后端入门篇)

Element&#xff08;Java后端入门篇&#xff09; Element:是饿了么公司前端开发团队提供的一套基于Vue的网站组件库&#xff0c;用于快速构建网页组件&#xff1a;组成网页的部件&#xff0c;例如超链接、按钮、图片、表格等等~ Element快速入门 引入Element的css、js文件和V…...

qt5和gstreamer开发环境安装配置

构建KDE虚拟机环境 1、安装virtualBox 2、导入镜像 配置QtCreator开发环境 https://blog.csdn.net/weixin_45824067/article/details/131970558&#xff08;安装的是qt6&#xff09; https://blog.csdn.net/m0_70849943/article/details/132472950 (安装的qt版本为5.14.2&…...

基于Python3的数据结构与算法 - 10 计数排序

一、问题 对列表进行排序&#xff0c;已知列表中的数范围都在0到100之间。设计时间复杂度为O(n)的算法。 二、解决思路 我们已知数字的范围&#xff0c;那么我们可以将数字的个数得到&#xff1a; 例如&#xff1a;有一个0~5的列表 [1,3,2,4,1,2,3,1,3,5] 则共有0个0&am…...

力扣206反转链表

206.反转链表 力扣题目链接(opens new window) 题意&#xff1a;反转一个单链表。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 1&#xff0c;双指针 2&#xff0c;递归。递归参考双指针更容易写&#xff0c; 为什么不用头插…...

【python实战】--图片创作视频

系列文章目录 文章目录 系列文章目录前言一、VideoWriter_fourcc()常见的编码参数二、使用步骤1.引入库 总结 前言 一、VideoWriter_fourcc()常见的编码参数 cv2.VideoWriter_fourcc(‘M’, ‘P’, ‘4’, ‘V’)MPEG-4编码 .mp4 可指定结果视频的大小cv2.VideoWriter_fourcc…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...