我有一些旧的代码,这些代码是用来链接到旧版本的openssl的。该代码的一部分从PEM文件加载密钥,并尝试通过使用以下代码来理解该密钥是私钥还是公钥:
if( (prv->p==0 || prv->q==0) ) {
// This is not a private key!
throw error("No private key for decryption");
}
对于最新版本的openssl,这(合理的)不能编译:
crypto.cpp: In function ‘key* decrypt_header(file_t, RSA*)’:
crypto.cpp:158:13: error: invalid use of incomplete type ‘RSA {aka struct rsa_st}’
if( (prv->p==0 || prv->q==0) ) {
^~
我知道对结构体的私有成员的直接访问被一个函数取代了,但是我很难弄清楚是哪个函数。
crypto.cpp:158:13: error: invalid use of incomplete type ‘RSA {aka struct rsa_st}’
if( (prv->p==0 || prv->q==0) ) {
^~
如你所知,OpenSSL 1.1.0改变了许多结构体成员的可见性。您不能再直接访问成员。相反,你必须使用getter和setter函数。
Try RSA_get0_factors
。get0
表示引用计数是而不是递增的。Do not BN_free
them.
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
如果代码支持多个版本的OpenSSL,那么您将需要一个保护,因为RSA_get0_factors
适用于OpenSSL 1.1.0及以上版本。也许像下面这样。参见OPENSSL_VERSION_NUMBER
手册页。
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER < 0x10100000L
/* OpenSSL 1.0.2 and below (old code) */
#else
/* OpenSSL 1.1.0 and above (new code) */
#endif
在1.1.1之后,OpenSSL支持getter返回每个参数。
const BIGNUM *RSA_get0_n(const RSA *d);
const BIGNUM *RSA_get0_e(const RSA *d);
const BIGNUM *RSA_get0_d(const RSA *d);
const BIGNUM *RSA_get0_p(const RSA *d);
const BIGNUM *RSA_get0_q(const RSA *d);
const BIGNUM *RSA_get0_dmp1(const RSA *r);
const BIGNUM *RSA_get0_dmq1(const RSA *r);
const BIGNUM *RSA_get0_iqmp(const RSA *r);
所以如果你不需要考虑以下版本的OpenSSL低于1.1.1这些代码将使代码简单。其他结构也支持这个getter。你可以在这里找到更多关于函数的信息。https://www.openssl.org/docs/man1.1.1/man3/
#if OPENSSL_VERSION_NUMBER < 0x10100005L
static void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d, const BIGNUM **p, const BIGNUM **q)
{
if(n != NULL)
*n = r->n;
if(e != NULL)
*e = r->e;
if(d != NULL)
*d = r->d;
if(p != NULL)
*p = r->p;
if(q != NULL)
*q = r->q;
}
#endif
const BIGNUM *bn_p;
const BIGNUM *bn_q;
RSA_get0_key(key, NULL, NULL, NULL, &bn_p, &bn_q);
/* if( (prv->p==0 || prv->q==0) ) { */
if( (prv_p==0 || prv_q==0) ) {