本文介绍一种方法使得通过RSA_private_decrypt函数可以使用CSP中的私钥来进行解密和通过RSA_sign函数可以使用CSP中的私钥来进行签名。
在openssl中RSA结构既可以表示公钥也可以表示私钥,它有一个类型为RSA_METHOD的域meth,该域包含一组实现RSA运算的函数指针。为了可以调用CSP,我们只需要实现一个特殊的RSA私钥,它包含有自己的RSA_METHOD结构。由于很多CSP中通常不都能获取明文的私钥,所以,我们实现的RSA私钥结构中只能包含有公钥信息,即n和e,然后根据公钥寻找到匹配的私钥句柄来进行相关的操作。具体来说,我们实现了一个函数:RSA *RSAToCAPIPrivKey(RSA *rsa)。该函数的参数是个RSA公钥,返回的是一个能够调用CSP私钥的RSA私钥。
具体的实现如下:
1、从个人证书库中寻找存在私钥且和给定公钥相匹配的证书,如果不存在,则返回NULL
2、用RSA_new()创建一个新的RSA结构,把公钥的n和e复制过去
3、设置新的RSA结构的flags为RSA_FLAG_SIGN_VER,并为之设置一个可以调用CSP的RSA_METHOD结构
4、返回该RSA结构。
实现的关键是RSA_METHOD结构。
Code
RSA_METHOD结构的定义如下:
struct rsa_meth_st
{
const 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);
int (*rsa_mod_exp)(BIGNUM *r0,const BIGNUM *I,RSA *rsa,BN_CTX *ctx);
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,BN_MONT_CTX *m_ctx);
int (*init)(RSA *rsa);
int (*finish)(RSA *rsa);
int flags;
char *app_data;
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,
unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
};
typedef struct rsa_meth_st RSA_METHOD;
name--是RSA_METHOD的名称
rsa_pub_enc--是RSA公钥加密的实现,RSA_public_encrypt就是由它实现的。我们不需要实现它。
rsa_pub_dec--是RSA公钥解密的实现,RSA_public_decrypt就是由它实现的。我们也不需要实现它。如果RSA结构的flags域没有设置了RSA_FLAG_SIGN_VER或者没有实现rsa_verify,则RSA_verify也会使用它来验证签名。
rsa_priv_enc--是RSA私钥加密的实现,RSA_private_encrypt就是由它实现的。我不知道怎么实现它。如果RSA结构的flags域没有设置了RSA_FLAG_SIGN_VER或者没有实现rsa_sign,则RSA_sign也会使用它来进行签名。
rsa_priv_dec--是RSA私钥解密的实现,RSA_private_decrypt就是由它实现的。这是我们要实现的。
rsa_mod_exp和bn_mod_exp是用来辅佐实现RSA算法的某些大整数运算的实现,具体我不清楚。我们也不需要实现它。
init--初始化函数,RSA_new会调用它。我们也不需要实现它。
finish--清理函数,RSA_free会调用它。我们也不需要实现它。
flags--某些标志
app_data--某些相关数据。我们也不需要它。
rsa_sign--如果RSA结构的flags域设置了RSA_FLAG_SIGN_VER(也就是rsa->flags & RSA_FLAG_SIGN_VER为真)且rsa_sign不为NULL的时候,RSA_sign会使用它来进行签名。这是我们要实现的。
rsa_verify--如果RSA结构的flags域设置了RSA_FLAG_SIGN_VER(也就是rsa->flags & RSA_FLAG_SIGN_VER为真)且rsa_verify不为NULL的时候,RSA_verify会使用它来验证签名。我们也不需要实现它。
rsa_keygen--产生RSA密钥对的实现。如果不为NULL,RSA_generate_key_ex会使用它,否则使用内置的RSA密钥对的实现。我们也不需要实现它。
RSA_METHOD结构的定义如下:
struct rsa_meth_st
{
const 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);
int (*rsa_mod_exp)(BIGNUM *r0,const BIGNUM *I,RSA *rsa,BN_CTX *ctx);
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,BN_MONT_CTX *m_ctx);
int (*init)(RSA *rsa);
int (*finish)(RSA *rsa);
int flags;
char *app_data;
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,
unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
};
typedef struct rsa_meth_st RSA_METHOD;
name--是RSA_METHOD的名称
rsa_pub_enc--是RSA公钥加密的实现,RSA_public_encrypt就是由它实现的。我们不需要实现它。
rsa_pub_dec--是RSA公钥解密的实现,RSA_public_decrypt就是由它实现的。我们也不需要实现它。如果RSA结构的flags域没有设置了RSA_FLAG_SIGN_VER或者没有实现rsa_verify,则RSA_verify也会使用它来验证签名。
rsa_priv_enc--是RSA私钥加密的实现,RSA_private_encrypt就是由它实现的。我不知道怎么实现它。如果RSA结构的flags域没有设置了RSA_FLAG_SIGN_VER或者没有实现rsa_sign,则RSA_sign也会使用它来进行签名。
rsa_priv_dec--是RSA私钥解密的实现,RSA_private_decrypt就是由它实现的。这是我们要实现的。
rsa_mod_exp和bn_mod_exp是用来辅佐实现RSA算法的某些大整数运算的实现,具体我不清楚。我们也不需要实现它。
init--初始化函数,RSA_new会调用它。我们也不需要实现它。
finish--清理函数,RSA_free会调用它。我们也不需要实现它。
flags--某些标志
app_data--某些相关数据。我们也不需要它。
rsa_sign--如果RSA结构的flags域设置了RSA_FLAG_SIGN_VER(也就是rsa->flags & RSA_FLAG_SIGN_VER为真)且rsa_sign不为NULL的时候,RSA_sign会使用它来进行签名。这是我们要实现的。
rsa_verify--如果RSA结构的flags域设置了RSA_FLAG_SIGN_VER(也就是rsa->flags & RSA_FLAG_SIGN_VER为真)且rsa_verify不为NULL的时候,RSA_verify会使用它来验证签名。我们也不需要实现它。
rsa_keygen--产生RSA密钥对的实现。如果不为NULL,RSA_generate_key_ex会使用它,否则使用内置的RSA密钥对的实现。我们也不需要实现它。