概述
一:ENGINE的目的:
ENGINE是OPENSSL预留的加载第三方加密库,主要包括了动态库加载的代码和加密函数指针管理的一系列接口。如果要使用Engine(假设你已经加载上该Engine了),那么首先要Load该Engine(比如ENGINE_load_XXXX),然后选择要使用的算法或者使用支持的所有加密算法(有相关函数)。这样你的应用程序在调用加解密算法时,它就会指向你加载的动态库里的加解密算法,而不是原先的OPENSSL的libeay32.dll库里的加解密算法。
二:ENGINE原理:
使用你自己编译的加解密动态库里的函数的指针或硬件接口指针来替换OPENSSL
中默认的加解密函数,类似于HOOK,这样实现动态加载第三方密码库;
三:ENGINE操作流程:
例如替换RSA:
NO.1 声明你要替换的函数名称和其它内部使用的函数
NO.2 声明RSA_Method结构,要替换的函数就提供函数名,不提换就是NULL
了,还有其它的类型也要填上;
NO.3 利用Engine_init等一系列函数初始化ENGINE库(其实上就是在初始化加
解密算法),主要是绑定特定的函数指针(自定义)和结构或初始化硬件设备等等操作;
Engine_finish也是一样,做一些清理工作;
NO.4 实现真正的接口,包括RSA密钥结构的转换,如果是不能取出的私钥,要
保存硬件设备提供的指针(通常是HANDLE)等等操作。然后调用硬件的加密解密函数。
四:程序实例:(实现ENGINE)
NO.1 声明函数名称
static int rsaref_private_decrypt(int len, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
NO.2 声明RSA_Method结构
static RSA_METHOD rsaref_rsa =
{
"RSAref PKCS#1 RSA",
NULL;
NULL;
rsaref_private_encrypt,
NULL;
NULL;
NULL;
NULL,
NULL,
0,
NULL,
NULL,
NULL
};
NO.3 代码实现
static int rsaref_private_decrypt(int len, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
{
//真实代码
}
NO.4 初始化ENGINE
static int bind_rsaref(ENGINE *e)
{
if( !ENGINE_set_id(e, engine_rsaref_id)
|| !ENGINE_set_name(e, engine_rsaref_name)
|| !ENGINE_set_RSA(e, &rsaref_rsa)
)
return 0;
return 1;
}
int bind_helper(ENGINE *e, const char *id)
{
if(id && (strcmp(id, engine_rsaref_id) != 0))
return 0;
if(!bind_rsaref(e))
return 0;
return 1;
}
__declspec( dllexport ) void ENGINE_load_rsaref(void)
{
ENGINE *toadd = engine_rsaref();
if(!toadd)
return;
ENGINE_add(toadd);
}
五:操作ENGINE(使用ENGINE)
NO.1 加载ENGINE
一般是调用动态库中的ENGINE_load_XXXX(例子中是ENGINE_load_rsare),把ENGINE对象加载到系统中,其实就是在ENGINE对象和RSA的结构里了ENGINE对象(参见RSA结构中的ENGINE定义)建立了一个关联,这样在用到RSA算法时如果RSA中的ENGINE对象为NULL,则调用默认的加解密算法,否则调用ENGINE对象里的加解密算法。
NO.2 指定你所需要的ENGINE
应用程序中可能要用到不只一个ENGINE接口,它们按链表的形式组织在一起,
这样你就需要指定你需要的ENGINE接口;例:ENGINE *e = ENGINE_by_id("rsaref");
返回的ENGINE对象里就指向你自定义的加解密接口。
NO.3 选择算法
ENGINE_set_default(ENGINE *e, int Flag)
Flag Description
ENGINE_METHOD_ALL 使用所有存在的算法(默认)
ENGINE_METHOD_RSA 仅使用RSA算法
ENGINE_METHOD_DSA 仅使用DSA算法
ENGINE_METHOD_DH 仅使用DH算法
ENGINE_METHOD_RAND 仅使用随机数算法
ENGINE_METHOD_CIPHERS 仅使用对称加解密算法
ENGINE_METHOD_DIGESTS 仅使用摘要算法
NO.4 使用加解密算法
使用ENGINE替换了算法后不影响原用或现用所有对加解密函数的调用操作。
完整源码:
enginep11.h
#ifndef ENGINEP11_H
#define ENGINEP11_H
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
void ENGINE_load_pkcs11(void);
#endif
enginep11.c:
/*****************************************
pkcs11 engine demo
filename:enginep11.c
date:2005.08.12
by eboy(eboymcy@163.com)
*****************************************/
#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
#include "enginep11.h"
/****************************************************************************
* Constants used when creating the ENGINE *
***************************************************************************/
static const char *engine_p11_id = "pkcs11";
static const char *engine_p11_name = "pkcs11 engine support(by eboy)";
/****************************************************************************
* Functions to handle the engine *
***************************************************************************/
/* Initiator which is only present to make sure this engine looks available */
static int p11_init(ENGINE *e)
{
//printf("p11_init OK.[FILE:%s,LINE:%d]n",__FILE__,__LINE__);
return 1;
}
/* Finisher which is only present to make sure this engine looks available */
static int p11_finish(ENGINE *e)
{
// printf("p11_finish OK.[FILE:%s,LINE:%d]n",__FILE__,__LINE__);
return 1;
}
/* Destructor (complements the "ENGINE_ncipher()" constructor) */
static int p11_destroy(ENGINE *e)
{
//printf("p11_destroy OK.[FILE:%s,LINE:%d]n",__FILE__,__LINE__);
return 1;
}
/****************************************************************************
* Engine commands *
*****************************************************************************/
static const ENGINE_CMD_DEFN p11_cmd_defns[] =
{
{0, NULL, NULL, 0}
};
/****************************************************************************
* RSA functions *
*****************************************************************************/
static int p11_public_encrypt(int len, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
printf("n**************public_encrypt, my function called, success!***********nn");
return 0;
}
static int p11_private_decrypt(int len, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
return 0;
}
static RSA_METHOD p11_rsa =
{
"eboy's pkcs11 PKCS#1 RSA",
p11_public_encrypt,
NULL,
NULL,
p11_private_decrypt,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
NULL
};
/****************************************************************************
* Symetric cipher and digest function registrars *
*****************************************************************************/
static int p11_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid);
static int p11_digests(ENGINE *e, const EVP_MD **digest,
const int **nids, int nid);
static int p11_cipher_nids[] ={ NID_des_cbc, NID_des_ede3_cbc, NID_desx_cbc, 0 };
static int p11_digest_nids[] ={ NID_md2, NID_md5, 0 };
/****************************************************************************
* Functions to handle the engine *
*****************************************************************************/
static void ERR_load_P11_strings()
{
//printf("ERR_load_P11_strings OK.[FILE:%s,LINE:%d]n",__FILE__,__LINE__);
return;
}
static int bind_p11(ENGINE *e)
{
//const RSA_METHOD *meth1;
if(!ENGINE_set_id(e, engine_p11_id)
|| !ENGINE_set_name(e, engine_p11_name)
|| !ENGINE_set_RSA(e, &p11_rsa)
//|| !ENGINE_set_ciphers(e, p11_ciphers)
//|| !ENGINE_set_digests(e, p11_digests)
|| !ENGINE_set_destroy_function(e, p11_destroy)
|| !ENGINE_set_init_function(e, p11_init)
|| !ENGINE_set_finish_function(e, p11_finish)
/* || !ENGINE_set_ctrl_function(e, p11_ctrl) */
/* || !ENGINE_set_cmd_defns(e, p11_cmd_defns) */)
return 0;
/* Ensure the p11 error handling is set up */
ERR_load_P11_strings();
return 1;
}
#ifdef ENGINE_DYNAMIC_SUPPORT
static int bind_helper(ENGINE *e, const char *id)
{
if(id && (strcmp(id, engine_p11_id) != 0))
return 0;
if(!bind_p11(e))
return 0;
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
#else
static ENGINE *engine_p11(void)
{
ENGINE *ret = ENGINE_new();
if(!ret)
return NULL;
if(!bind_p11(ret))
{
ENGINE_free(ret);
return NULL;
}
return ret;
}
void ENGINE_load_pkcs11(void)
{
/* Copied from eng_[openssl|dyn].c */
ENGINE *toadd = engine_p11();
if(!toadd) return;
ENGINE_add(toadd);
ENGINE_free(toadd);
ERR_clear_error();
}
#endif
/*****************************************
pkcs11 engine demo
filename:enginep11.c
date:2005.08.12
by eboy(eboymcy@163.com)
*****************************************/
#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
#include "enginep11.h"
/****************************************************************************
* Constants used when creating the ENGINE *
***************************************************************************/
static const char *engine_p11_id = "pkcs11";
static const char *engine_p11_name = "pkcs11 engine support(by eboy)";
/****************************************************************************
* Functions to handle the engine *
***************************************************************************/
/* Initiator which is only present to make sure this engine looks available */
static int p11_init(ENGINE *e)
{
//printf("p11_init OK.[FILE:%s,LINE:%d]n",__FILE__,__LINE__);
return 1;
}
/* Finisher which is only present to make sure this engine looks available */
static int p11_finish(ENGINE *e)
{
// printf("p11_finish OK.[FILE:%s,LINE:%d]n",__FILE__,__LINE__);
return 1;
}
/* Destructor (complements the "ENGINE_ncipher()" constructor) */
static int p11_destroy(ENGINE *e)
{
//printf("p11_destroy OK.[FILE:%s,LINE:%d]n",__FILE__,__LINE__);
return 1;
}
/****************************************************************************
* Engine commands *
*****************************************************************************/
static const ENGINE_CMD_DEFN p11_cmd_defns[] =
{
{0, NULL, NULL, 0}
};
/****************************************************************************
* RSA functions *
*****************************************************************************/
static int p11_public_encrypt(int len, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
printf("n**************public_encrypt, my function called, success!***********nn");
return 0;
}
static int p11_private_decrypt(int len, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
return 0;
}
static RSA_METHOD p11_rsa =
{
"eboy's pkcs11 PKCS#1 RSA",
p11_public_encrypt,
NULL,
NULL,
p11_private_decrypt,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
NULL
};
/****************************************************************************
* Symetric cipher and digest function registrars *
*****************************************************************************/
static int p11_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid);
static int p11_digests(ENGINE *e, const EVP_MD **digest,
const int **nids, int nid);
static int p11_cipher_nids[] ={ NID_des_cbc, NID_des_ede3_cbc, NID_desx_cbc, 0 };
static int p11_digest_nids[] ={ NID_md2, NID_md5, 0 };
/****************************************************************************
* Functions to handle the engine *
*****************************************************************************/
static void ERR_load_P11_strings()
{
//printf("ERR_load_P11_strings OK.[FILE:%s,LINE:%d]n",__FILE__,__LINE__);
return;
}
static int bind_p11(ENGINE *e)
{
//const RSA_METHOD *meth1;
if(!ENGINE_set_id(e, engine_p11_id)
|| !ENGINE_set_name(e, engine_p11_name)
|| !ENGINE_set_RSA(e, &p11_rsa)
//|| !ENGINE_set_ciphers(e, p11_ciphers)
//|| !ENGINE_set_digests(e, p11_digests)
|| !ENGINE_set_destroy_function(e, p11_destroy)
|| !ENGINE_set_init_function(e, p11_init)
|| !ENGINE_set_finish_function(e, p11_finish)
/* || !ENGINE_set_ctrl_function(e, p11_ctrl) */
/* || !ENGINE_set_cmd_defns(e, p11_cmd_defns) */)
return 0;
/* Ensure the p11 error handling is set up */
ERR_load_P11_strings();
return 1;
}
#ifdef ENGINE_DYNAMIC_SUPPORT
static int bind_helper(ENGINE *e, const char *id)
{
if(id && (strcmp(id, engine_p11_id) != 0))
return 0;
if(!bind_p11(e))
return 0;
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
#else
static ENGINE *engine_p11(void)
{
ENGINE *ret = ENGINE_new();
if(!ret)
return NULL;
if(!bind_p11(ret))
{
ENGINE_free(ret);
return NULL;
}
return ret;
}
void ENGINE_load_pkcs11(void)
{
/* Copied from eng_[openssl|dyn].c */
ENGINE *toadd = engine_p11();
if(!toadd) return;
ENGINE_add(toadd);
ENGINE_free(toadd);
ERR_clear_error();
}
#endif
test.c:
//test.c
#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
#include "enginep11.h"
static void display_engine_list()
{
ENGINE *h;
int loop;
h = ENGINE_get_first();
loop = 0;
printf("listing available engine typesn");
while(h)
{
printf("engine %i, id = "%s", name = "%s"n",
loop++, ENGINE_get_id(h), ENGINE_get_name(h));
h = ENGINE_get_next(h);
}
printf("end of listn");
/* ENGINE_get_first() increases the struct_ref counter, so we
must call ENGINE_free() to decrease it again */
ENGINE_free(h);
}
void test()
{
ENGINE *p11_engine = NULL;
int rv;
unsigned char buf[1024];
RSA *rsa;
EVP_PKEY *evpKey;
ENGINE_load_pkcs11();
//display_engine_list();
p11_engine = ENGINE_by_id("pkcs11");
if(p11_engine == NULL)
{
printf("get pkcs11 engine Errorn");
return ;
}
printf("get pkcs11 engine OK.name:%sn",ENGINE_get_name(p11_engine));
ENGINE_register_RSA(p11_engine);
rv = ENGINE_set_default(p11_engine,ENGINE_METHOD_ALL);
evpKey = EVP_PKEY_new();
rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
rv = EVP_PKEY_set1_RSA(evpKey,rsa);
rv = EVP_PKEY_encrypt(buf,buf,128,evpKey);
rv = ENGINE_finish(p11_engine);
rv = ENGINE_free(p11_engine);
printf("test end.n");
return;
}
int main()
{
test();
return 0;
}
编译:
# gcc -g ./enginep11.h ./enginep11.c ./test.c -o test -lssl
运行:
# ./test
结果:
engine 0, id = "pkcs11", name = "pkcs11 engine support(by eboy)"
get pkcs11 engine OK. name:pkcs11 engine support(by eboy)
**************public_encrypt, my function called, success!***********
test end.
加解密在函数p11_public_encrypt和p11_private_decrypt中进行。
各个openssl版本函数借口有差距,请参考相关源码程序。
engine正宗的例子在openssl目录中有
cryptoengineenginetest.c
http://blog.chinaunix.net/uid-7811535-id-2043455.html
最后
以上就是机智奇迹为你收集整理的利用ENGINE替换OPENSSL中的加解密算法的全部内容,希望文章能够帮你解决利用ENGINE替换OPENSSL中的加解密算法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复