OPENSSL ENGINE概述
能够使用户比较容易地将自己的硬件加入到openssl中去,替换其提供的软件算法。一个Engine提供了密码计算中各种计算方法的集合,它用于控制openssl的各种密码计算。
OPENSSL ENGINE实现:
OPENSSL ENGINE替换第三方算法方法:OPENSSL算法库中每一个算法对应一个唯一的NID,第三方算法绑定已有的NID,OPENSSL加密库算法的函数指针就会被第三方软件加密库的函数指针或硬件加密模块的接口指针替换掉
向OPENSSL协议库中注册第三方算法
加载引擎后可以使用新注册的算法(注册NID),对OPENSSL加密库中原有的算法的使用不影响,缺点需要修改源码,相对麻烦。
第三方算法替换OPENSSL协议库指定原算法
第三方加密算法通过绑定算法NID,替换OPENSSL加密库同NID算法,加载引擎后OPENSSL加密库中被换掉的算法将无法使用,无需修改 OpenSSL 源代码,实现容易,也经常被采用。
下面通过第二种方法实现ENGINE
ENGINE实现通过init、finis、destory三个函数在bind函数中体现文章来源:https://www.toymoban.com/news/detail-664756.html
下面以RSA为例文章来源地址https://www.toymoban.com/news/detail-664756.html
/*rsa_engine.c文件*/
#include "rsa_engine.h"
#include <stdio.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <openssl/evp.h>
static const char *engine_id="RSA123"; //engine id
static const char *engine_name="RSA enging support"; //engine name
static int rsa_sign(int type,const unsigned char *m, unsigned int m_length,unsigned char *sigret, unsigned int *siglen,const RSA *rsa)
{
printf("rsa_sign \n");
return 1;
}
static int rsa_verify (int dtype, const unsigned char *m,unsigned int m_length, const unsigned char *sigbuf,unsigned int siglen, const RSA *rsa)
{
printf("rsa_verify \n");
return 1;
}
static int rsa_pub_enc(int flen, const unsigned char *from,unsigned char *to, RSA *rsa, int padding)
{
printf("**************rsa_pub_enc, my function called, success!***********\n");
return 1;
}
static int rsa_pub_dec(int flen, const unsigned char *from,unsigned char *to, RSA *rsa, int padding)
{
printf("**************rsa_pub_dec, my function called, success!***********\n");
return 1;
}
//初始化 RSA方法的结构体
static RSA_METHOD rsa_pp =
{
"RSA eg",
rsa_pub_enc,
rsa_pub_dec,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
rsa_sign,
rsa_verify,
NULL
};
//初始化
static int rsa_init(ENGINE *e)
{
printf("rsa engine init\n");
return 1;
}
static int rsa_finish(ENGINE *e)
{
printf("rsa engine finish\n");
return 1;
}
//回收
static int rsa_destory(ENGINE *e)
{
printf("rsa engine destory\n");
return 1;
}
//注册函数
static int bind_pp(ENGINE *e)
{
if(!ENGINE_set_id(e,engine_id)||
!ENGINE_set_name(e,engine_name)||
!ENGINE_set_RSA(e,&rsa_pp)||
!ENGINE_set_destroy_function(e,rsa_destory)||
!ENGINE_set_init_function(e,rsa_init)||
!ENGINE_set_finish_function(e,rsa_finish))
return 0;
printf("ERR_load_rsa success\n");
return 1;
}
static int bind_helper(ENGINE *e, const char *id)
{
if(id && (strcmp(id, engine_id) != 0))
return 0;
if(!bind_pp(e))
return 0;
return 1;
}
//通过ENGINE_load_XX方式通过动态方式调用
#ifdef ENGINE_DYNAMIC_SUPPORT
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
#else
static ENGINE *engine_rsa(void)
{
ENGINE *ret = ENGINE_new();
if(!ret)
return NULL;
if(!bind_pp(ret))
{
ENGINE_free(ret);
return NULL;
}
return ret;
}
void ENGINE_load_rsapp(void)
{
ENGINE *rsa_st = engine_rsa();
if(!rsa_st)
return;
ENGINE_add(rsa_st);
ENGINE_free(rsa_st);
ERR_clear_error();
}
#endif
#if 1
int main()
{
ENGINE_load_rsapp(); //加载引擎
ENGINE *rsa_st = NULL;
rsa_st = ENGINE_by_id("RSA123"); //通过id返回ENGINE对象
if(rsa_st == NULL)
{
printf("get pkcs11 engine Error\n");
return 0;
}
printf("name:%s\n",ENGINE_get_name(rsa_st));
int inl,outl,total,dtotal;
RSA *rkey;
RSA_METHOD *rsa_m;
EVP_PKEY *ek,*pkey;
rkey=RSA_new_method(rsa_st);
printf("rkey:%s\n",rkey);
pkey=EVP_PKEY_new();
EVP_PKEY_set1_RSA(pkey,rkey);
ENGINE_register_RSA(rsa_st); //
ENGINE_set_default(rsa_st,ENGINE_METHOD_RSA);
unsigned char from[128]="aaaaaaaaa";
unsigned char out[1024]={0};
RSA_public_encrypt(sizeof(from),from,out,rkey,1);
printf("crt:%s\n",out);
RSA_public_decrypt(sizeof(out),out,from,rkey,1);
printf("crt:%s\n",from);
rv = ENGINE_finish(rsa_st);
printf("test end.\n");
}
#endif
/*rsa_engine.h*/
#ifndef rsa_engine_H
#define rsa_engine_H
#include <openssl/engine.h>
struct rsa_meth_st {
char *name;
int (*rsa_pub_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int (*rsa_pub_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int (*rsa_priv_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int (*rsa_priv_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
/* Can be null */
int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
/* Can be null */
int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
/* called at new */
int (*init) (RSA *rsa);
/* called at free */
int (*finish) (RSA *rsa);
/* RSA_METHOD_FLAG_* things */
int flags;
/* may be needed! */
char *app_data;
/*
* New sign and verify functions: some libraries don't allow arbitrary
* data to be signed/verified: this allows them to be used. Note: for
* this to work the RSA_public_decrypt() and RSA_private_encrypt() should
* *NOT* be used RSA_sign(), RSA_verify() should be used instead.
*/
int (*rsa_sign) (int type,
const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen,
const RSA *rsa);
int (*rsa_verify) (int dtype, const unsigned char *m,
unsigned int m_length, const unsigned char *sigbuf,
unsigned int siglen, const RSA *rsa);
/*
* If this callback is NULL, the builtin software RSA key-gen will be
* used. This is for behavioural compatibility whilst the code gets
* rewired, but one day it would be nice to assume there are no such
* things as "builtin software" implementations.
*/
int (*rsa_keygen) (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
int (*rsa_multi_prime_keygen) (RSA *rsa, int bits, int primes,
BIGNUM *e, BN_GENCB *cb);
};
void ENGINE_load_rsapp(void);
#endif // DEBUG
编译
gcc rsa_engine.c -lssl -lcrypto
到了这里,关于openssl engine实现和原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!