OpenSSL Engine的三种加载方式
https://www.518cn.com 发布时间:2025-03-18 18:52 作者:网络
摘要:本文测试代码基于Openssl版本:1.1.1f 创建一个Engine lib #include openssl/evp.h #include openssl/engine.h #include iostream static int encryptf
本文测试代码基于Openssl版本:1.1.1f
创建一个Engine lib
#include <openssl/evp.h>
#include <openssl/engine.h>
#include <iostream>
static int encryptfn(EVP_PKEY_CTX *ctx,unsigned char *out,size_t *outlen,const unsigned char *in,size_t inlen){
*outlen = 1;
std::cout << "encryptfn call" << std::endl;
return 1;
}
static int test_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
const int **pnids, int nid)
{
static const int rnid = EVP_PKEY_RSA;
if (pmeth == NULL) {
*pnids = &rnid;
return 1;
}
if (nid == EVP_PKEY_RSA) {
EVP_PKEY_METHOD* method{EVP_PKEY_meth_new(0,0)};
EVP_PKEY_meth_set_encrypt(method, nullptr, encryptfn);//设置自定义方法
*pmeth = method;
return 1;
}
*pmeth = NULL;
return 0;
}
static std::int32_t bind(ENGINE* const e, const char* const id) {
std::int32_t ret{0};
ENGINE_set_id(e,"test_ID");
ENGINE_set_name(e,"test_name");
ENGINE_set_pkey_meths(e,test_pkey_meths);
return 1;
}
extern "C" std::int32_t bind_engine(ENGINE* const e, const char* const id,
const dynamic_fns* const fns);
extern "C" std::int32_t bind_engine(ENGINE* const e, const char* const id,
const dynamic_fns* const fns) {
if (ENGINE_get_static_state() == fns->static_state) {
if (0 == bind(e, id)) {
return 0;
}
return 1;
}
static_cast<void>(CRYPTO_set_mem_functions(
fns->mem_fns.malloc_fn, fns->mem_fns.realloc_fn, fns->mem_fns.free_fn));
if (0 == bind(e, id)) {
return 0;
}
return 1;
}
extern "C" uint64_t v_check(const uint64_t v) noexcept;
extern "C" uint64_t v_check(const uint64_t v) noexcept {
if (v >= static_cast<uint64_t>(0x00030000U)) {
return static_cast<uint64_t>(0x00030000U);
}
return 0U;
}
编译动态库:g -fPIC -shared engine_evp_so.cpp -o libengine_evp.so
Engine 加载方式1:cmd加载
方法1:openssl cmd加载
> engine dynamic -pre SO_PATH:/yourpath/libengine_evp.so -pre LOAD
(dynamic) Dynamic engine loading support
[Success]: SO_PATH:/yourpath/libengine_evp.so
[Success]: LOAD
Loaded: (test_ID) test_name
方法2:进程中调用cmd函数加载
在代码中使用ENGINE_ctrl_cmd_string()调用cmd能力来加载engine
#include <openssl/rsa.h>
#include <openssl/engine.h>
#include <iostream>
void dump_hex(const uint8_t *hex, uint32_t size) {
uint32_t i = 0;
for (i = 0; i < size; i) {
if ((i % 8) == 0) {
printf("n");
}
printf("0xx ", hex[i]);
}
printf("n");
}
RSA* rsa_create(){
RSA* rsa = RSA_new();//分配空间
BIGNUM* pBNe = BN_new();//分配空间
BN_set_word(pBNe, RSA_F4);
int ret = RSA_generate_key_ex(rsa, 1024, pBNe, NULL);
if(ret < 0 ){
printf("encrypt failed, ret:%d n", ret);
return nullptr;
}
BN_free(pBNe);
return rsa;
}
int main(){
ENGINE_load_dynamic();//加载dynamic engine
ENGINE* engine = ENGINE_by_id("dynamic");
if(engine == nullptr){
std::cout << "ENGINE_by_id" << std::endl;
}
int ret{};
ret = ENGINE_ctrl_cmd_string(engine, "SO_PATH", "engine_evp", 0);//libengine_evp.so
if(ret == 0){
std::cout << "ENGINE_ctrl_cmd_string0" << std::endl;
}
ret = ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0);//load engine
if(ret == 0){
std::cout << "ENGINE_ctrl_cmd_string1" << std::endl;
}
RSA* rsa = rsa_create();
if(rsa == nullptr){
std::cout << "Read_Key" << std::endl;
}
EVP_PKEY* pkey = EVP_PKEY_new();
ret = EVP_PKEY_assign_RSA(pkey, rsa);
if(ret == 0){
std::cout << "EVP_PKEY_assign_RSA" << std::endl;
}
EVP_PKEY_CTX* ctx;
ctx = EVP_PKEY_CTX_new(pkey, engine);
if (ctx == nullptr) {
std::cout << "EVP_PKEY_CTX_new" << std::endl;
ERR_print_errors_fp(stderr);
}
ret = EVP_PKEY_encrypt_init(ctx);
if (ret == 0) {
std::cout << "EVP_PKEY_encrypt_init" << std::endl;
}
ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
if (ret == 0) {
std::cout << "EVP_PKEY_CTX_set_rsa_padding" << std::endl;
}
int plaintext_len = 100;
unsigned char plaintext[plaintext_len]{"123"};
std::cout << "plaintext: " << std::endl;
std::cout << plaintext << std::endl;
size_t ciphertext_len;
ret = EVP_PKEY_encrypt(ctx, nullptr, &ciphertext_len, plaintext, plaintext_len);
if (ret == 0) {
std::cout << "EVP_PKEY_encrypt" << std::endl;
}
std::cout << "ciphertext_len: " << ciphertext_len << std::endl;
return 0;
}
运行前记得配置环境变量:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/DirToYourLib
Engine 加载方式2:加载conf文件
方法1:进程中加载指定的配置文件
首先准备好配置文件openssl.cnf,存放在任意位置
填入engine_id,动态库lib位置填入dynamic_path
openssl_conf = openssl_def
[openssl_def]
engines = engine_section
[engine_section]
engine_test = engine_test_section
[engine_test_section]
engine_id = test_ID
dynamic_path = /yourpath/libengine_evp.so
default_algorithms = ALL
init = 1
在代码中使用CONF_modules_load_file()手动加载配置文件
#include <openssl/rsa.h>
#include <openssl/engine.h>
#include <openssl/conf.h>
#include <iostream>
void dump_hex(const uint8_t *hex, uint32_t size) {
uint32_t i = 0;
for (i = 0; i < size; i) {
if ((i % 8) == 0) {
printf("n");
}
printf("0xx ", hex[i]);
}
printf("n");
}
RSA* rsa_create(){
RSA* rsa = RSA_new();//分配空间
BIGNUM* pBNe = BN_new();//分配空间
BN_set_word(pBNe, RSA_F4);
int ret = RSA_generate_key_ex(rsa, 1024, pBNe, NULL);
if(ret < 0 ){
printf("encrypt failed, ret:%d n", ret);
return nullptr;
}
BN_free(pBNe);
return rsa;
}
int main(){
OPENSSL_load_builtin_modules();
ENGINE_load_dynamic();
int ret{CONF_modules_load_file("/yourpath/openssl.cnf", "openssl_conf", 0)};//读取配置文件
if (ret == 0) {
std::cout << "CONF_modules_load_file" << std::endl;
}
ENGINE* engine = ENGINE_by_id("test_ID");//通过id找到engine
if(engine == nullptr){
std::cout << "ENGINE_by_id" << std::endl;
ERR_print_errors_fp(stderr);
}
RSA* rsa = rsa_create();
if(rsa == nullptr){
std::cout << "Read_Key" << std::endl;
}
EVP_PKEY* pkey = EVP_PKEY_new();
ret = EVP_PKEY_assign_RSA(pkey, rsa);
if(ret == 0){
std::cout << "EVP_PKEY_assign_RSA" << std::endl;
}
EVP_PKEY_CTX* ctx;
ctx = EVP_PKEY_CTX_new(pkey, engine);//使用engine能力
if (ctx == nullptr) {
std::cout << "EVP_PKEY_CTX_new" << std::endl;
ERR_print_errors_fp(stderr);
}
ret = EVP_PKEY_encrypt_init(ctx);
if (ret == 0) {
std::cout << "EVP_PKEY_encrypt_init" << std::endl;
}
ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
if (ret == 0) {
std::cout << "EVP_PKEY_CTX_set_rsa_padding" << std::endl;
}
int plaintext_len = 100;
unsigned char plaintext[plaintext_len]{"123"};
std::cout << "plaintext: " << std::endl;
std::cout << plaintext << std::endl;
size_t ciphertext_len;
ret = EVP_PKEY_encrypt(ctx, nullptr, &ciphertext_len, plaintext, plaintext_len);//先获取ciphertext_len
if (ret == 0) {
std::cout << "EVP_PKEY_encrypt" << std::endl;
}
std::cout << "ciphertext_len: " << ciphertext_len << std::endl;
return 0;
}
编译:g engine_conf.cpp -lcrypto
无需配置环境变量
方法2:在进程中根据环境变量自动加载conf配置文件
配置环境变量:export OPENSSL_CONF=/path/to/openssl.cnf
代码如下,和上小节的代码对比,只有main函数的前几行做修改
int main(){
OPENSSL_config("openssl_conf"); //加载配置文件
ENGINE* engine = ENGINE_by_id("test_ID");//根据id得到engine
if(engine == nullptr){
std::cout << "ENGINE_by_id" << std::endl;
ERR_print_errors_fp(stderr);
}
RSA* rsa = rsa_create();
if(rsa == nullptr){
std::cout << "Read_Key" << std::endl;
}
EVP_PKEY* pkey = EVP_PKEY_new();
int ret = EVP_PKEY_assign_RSA(pkey, rsa);
if(ret == 0){
std::cout << "EVP_PKEY_assign_RSA" << std::endl;
}
...
总结
本文总结了三种OpenSSL Engine的加载方式,给出了编程示例
相关文章
- 子母钟系统,安徽京准助力高考精准时间 子母钟系统,安徽京准助力高考精准时间 京准电子科...03-18
- 京准电钟:NTP校时服务器于安防监控系统应用方案 京准电钟:NTP校时服务器于安防监控系统应...03-18
- 参考视频:https://www.bilibili.com/video/BV1itwgeHEEk/?spm_id_from=333.1387.upload.video_card.click&vd_source=e9...03-18
- 京准电钟:NTP精密时钟服务器在自动化系统中的作用 京准电钟:NTP精密时钟服务器在自动化系...03-18
EWM181-Z12S简易型zigbee3.0模块的技术解析与应用指南
一、产品概述:重新定义低功耗无线通信 EWM181-Z12S是简单易用型工业级ZigBee3.0无线模块,支持...03-18- 这里要说的是,用户登录密码属于用户隐私数据。首先,隐私数据属于敏感数据,不能明文传...03-18
- 本文将介绍 TOPIAM 与 Wiki 集成步骤详细指南。 应用简介 Wiki.js 是一款高度可定制...03-18
- 官方下载 夸克网盘 Kali Linux 2021.3具有以下优势: 增强的OpenSSL兼容性 扩大连接范围:重新配置...03-18
- 一.ELF文件结构 0x01什么是ELF文件 1.linux环境中,二进制可持性文件的类型是ELF(Executable and Link...03-18
- 京准电钟:北斗卫星校时器助力智慧电子政务系统 京准电钟:北斗卫星校时器助力智慧电子政...03-18
最新评论