OpenSSL之PKey的EVP封装

时间:2022-11-21 18:24:48

在Openssl中,非对称加密涉及到两个密钥。一个为公开的密钥(公钥),一个为非公开的密钥。而OpenSSL中非对称加密算法有RSA、DSA、ECC,他们的原理不同,因此其密钥结构不同。下面我们列出我们关心的密钥部分。

1)非对称算法密钥结构

OpenSSL中,生产密钥的算法通过以下几个函数

int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
int DSA_generate_key(DSA *dsa);
int EC_KEY_generate_key(EC_KEY *eckey);
int DH_generate_key(DH *dh);

由以上几个函数可以知道生成的密钥都在RSA、DSA、ECKEY 、DH结构体中

RSA 结构rsa.h中,其中{n,e} 表示公钥,{n, d}表示私钥

struct rsa_st
{
.....
BIGNUM *n;
BIGNUM *e;
BIGNUM *d;
BIGNUM *p;
BIGNUM *q;
BIGNUM *dmp1;
BIGNUM *dmq1;
BIGNUM *iqmp;
.....
};

DSA结构在dsa.h中

struct dsa_st
{
......
BIGNUM *p;
BIGNUM *q;/* == 20 */
BIGNUM *g;
BIGNUM *pub_key; /* y public key */
BIGNUM *priv_key; /* x private key */
......
};
ECC结构在ecc.h

struct ec_key_st {
EC_GROUP *group;
EC_POINT *pub_key;
BIGNUM *priv_key;
} /* EC_KEY */;
DH结构体在dh.h中定义

struct dh_st
{

BIGNUM *p;
BIGNUM *g;
long length; /* optional */
BIGNUM *pub_key;/* g^x */
BIGNUM *priv_key;/* x */
}

2)EVP封装中的密钥结构EVP_PKEY

struct evp_pkey_st
{
int type;
int save_type;
int references;
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *engine;
union{
char *ptr;
#ifndef OPENSSL_NO_RSA
struct rsa_st *rsa;/* RSA */
#endif
#ifndef OPENSSL_NO_DSA
struct dsa_st *dsa;/* DSA */
#endif
#ifndef OPENSSL_NO_DH
struct dh_st *dh;/* DH */
#endif
#ifndef OPENSSL_NO_EC
struct ec_key_st *ec;/* ECC */
#endif
} pkey;
int save_parameters;
STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
} /* EV

先上面的结构,结构体中有union结构,在union结构中分别定义rsa、dsa、dh、ec,这些不难理解,定义共用体的目的是节省内存,因为每次这个结构体只为一个非对称密码算法服务。而为什么定义一个ptr呢?这边封装的技巧就在这,ptr指向密钥结构的地址。不管生产的密钥是1)中哪一种类型结构,将其强制转化为char* 赋值给ptr。而当我们调用时,我们根据type的类型,直接进行调用。比如说:EVP_KEY *pkey;pkey->pkey.rsa;直接就将ptr当成rsa类型操作。这就是共用体的好处。下面一幅图是从Openssl中截取的代码片段来证明上面的分析。

OpenSSL之PKey的EVP封装

具体是用实例可以参考<openssl 编程> 赵春平