首页 > 其他分享 >OpenSSL Engine的三种加载方式

OpenSSL Engine的三种加载方式

时间:2024-07-24 18:06:34浏览次数:13  
标签:Engine engine return OpenSSL ret RSA include 加载

本文测试代码基于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("0x%02x ", 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("0x%02x ", 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的加载方式,给出了编程示例

标签:Engine,engine,return,OpenSSL,ret,RSA,include,加载
From: https://www.cnblogs.com/AndGate/p/18321424

相关文章

  • 【7.PIE-Engine案例—— 加载Terra星全球500m地表反射率8天合成产品(MOD09A1 V61)数据
    加载Terra星全球500m地表反射率8天合成产品(MOD09A1V61)数据集原始路径欢迎大家查看本案例原始来源最终结果具体代码/***@File:MOD09A1*@Time:2020/7/21*@Author:piesat*@Version:1.0*@Contact:400-890-0662*@License......
  • 自签openssl证书(包含泛域名)
    1、安装openSSLwegethttp://www.openssl.org/source/openssl-1.0.0a.tar.gzTar-zxvfopenssl-1.0.0a.tar.gz(1)进入openssl-1.0.0a目录通过编译方式安装openssl./config-prefix=/www/server/openssl#设置openssl安装路径2、生成自签证书(CA)(推荐在nginx下创建ssl目录)(......
  • Solaris11升级openssh和openssl
    源码编译升级openssl版本官网下载openssl-1.1.1d.targunzipopenssl-1.1.1d.tar.gztaropenssl-1.1.1d.tarcdopenssl-1.1.1d./config--prefix=/usr/local/sslsharedmakemakeinstall替换老版本:备份mv/usr/bin/openssl/usr/bin/openssl.oldmv/usr/i......
  • elementui中实现loding实现局部加载,以el-dialog为例
    效果 封装loading加载(也可以直接使用,封装为了方便多次调用)组件定义:loadDiy.jsimport{Loading}from"element-ui";exportconstservicesLoading=(node,str,lock)=>{returnLoading.service({target:document.querySelector(node),//loading需要覆盖的DO......
  • Android超复杂布局加载速度优化
    一、概述有时候由于实际业务的需要,或者产品经理或设计师考虑的不够全面,会导致某一个或某些页面的布局超级复杂。这些超级复杂的UI在经过程序员通过传统布局优化过后仍然是复杂的(优化布局层级、优化层级布局数量等)。这就会导致布局加载速度过于缓慢。直接的结果就是打开A......
  • Best practices for prompt engineering with the OpenAI API
    BestpracticesforpromptengineeringwiththeOpenAIAPIhttps://help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-the-openai-api HowpromptengineeringworksDuetothewayOpenAImodelsaretrained,therearespecificpr......
  • 为什么重新加载后“globals()”中会出现未声明的变量,并且使用它们来识别重新加载是否
    我发现重新加载模块时下面的代码片段test出乎意料地已经在globals()/locals()中定义了所有变量。为什么会发生这种情况?我注意到了这个"xxx"inlocals()模式|||BlenderPython脚本中有很多,因为人们通常使用它来检查模块之前......
  • 如何在 PySide 中从 .ui 文件加载子项?
    现在我像这样加载它们:if__name__=='__main__':app=QApplication(sys.argv)loader=QUiLoader()file=QFile('main.ui')file.open(QFile.ReadOnly)window=loader.load(file)file.close()window.show()#Here:......
  • 我如何为 yolov5 制作 gui,从 pytorch 和 opencv 加载到 tkinker?
    请帮助我,我不明白如何使用yolo和tkinker作为gui来制作用于实时检测的gui。以及如何将边界框从pytorch渲染到tkinker?这里是代码:importtorchfrommatplotlibimportpyplotaspltimportnumpyasnpimportcv2model=torch.hub.load('ultralytics/yolov5......
  • MySQL Architecture And Engine
    Author:ACatSmilingSince:2024-07-22SELECT的执行过程SELECT的查询结构方式一:SELECT...,...,...FROM...,...,...WHERE多表的连接条件AND不包含组函数的过滤条件GROUPBY...,...HAVING包含组函数的过滤条件ORDERBY...ASC/DESCLIMIT...,...;方式二......