升级OpenSSL 1.0.2至1.1.1k时evp_pkey_st等指针访问报错如何解决
问题根本原因
OpenSSL从1.1.0版本开始,将X509_STORE_CTX、EVP_PKEY等核心结构体的内部定义改为不对外公开的不透明类型,禁止代码直接访问结构体成员,必须使用官方提供的公开接口获取内部属性,这就是你遇到编译报错的核心原因。
修复方案
第一部分:X509_STORE_CTX 成员访问报错修复
原来直接访问vrfy_ctx->error的写法,替换为官方公开接口X509_STORE_CTX_get_error(vrfy_ctx)即可,修复后代码如下:
X509_STORE_CTX *vrfy_ctx = X509_STORE_CTX_new(); X509_STORE_CTX_init(vrfy_ctx, store, cert_x509, NULL); if(X509_verify_cert(vrfy_ctx) != 1) { // 替换原直接访问结构体成员的写法 int ctx_error = X509_STORE_CTX_get_error(vrfy_ctx); if(ignore_date) { switch(ctx_error) { case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CERT_HAS_EXPIRED: X509_STORE_CTX_free(vrfy_ctx); X509_STORE_free(store); return true; } } error_message = X509_verify_cert_error_string(ctx_error); X509 *error_cert = X509_STORE_CTX_get_current_cert(vrfy_ctx); X509_NAME *certsubject = X509_get_subject_name(error_cert); error_message += X509_NAME_oneline(certsubject, 0, 0); X509_free(error_cert); X509_STORE_CTX_free(vrfy_ctx); X509_STORE_free(store); return false; }
第二部分:EVP_PKEY 成员访问报错修复
需要修改两处逻辑:
- 获取公钥类型:原
pkey->type替换为EVP_PKEY_get_id(pkey),返回值和原有的公钥类型常量完全兼容 - 获取不同类型公钥的内部参数:不要直接访问
pkey->pkey.rsa这类成员,用对应的getter接口获取对应类型的结构体指针,再调用对应类型的属性获取接口拿参数
修复后代码如下:
std::string ssl_tools::public_key_type(X509 *x509) { EVP_PKEY *pkey=X509_get_pubkey(x509); // 替换原直接访问type成员的写法 int key_type = EVP_PKEY_get_id(pkey); EVP_PKEY_free(pkey); if (key_type==EVP_PKEY_RSA) return "RSA"; if (key_type==EVP_PKEY_DSA) return "DSA"; if (key_type==EVP_PKEY_DH) return "DH"; if (key_type==EVP_PKEY_EC) return "ECC"; return ""; } int ssl_tools::public_key_size(X509 *x509) { EVP_PKEY *pkey=X509_get_pubkey(x509); int key_type = EVP_PKEY_get_id(pkey); int keysize = -1; if (key_type == EVP_PKEY_RSA) { const RSA *rsa = EVP_PKEY_get0_RSA(pkey); if (rsa != nullptr) { keysize = BN_num_bits(RSA_get0_n(rsa)); } } else if (key_type == EVP_PKEY_DSA) { const DSA *dsa = EVP_PKEY_get0_DSA(pkey); if (dsa != nullptr) { keysize = BN_num_bits(DSA_get0_p(dsa)); } } else if (key_type == EVP_PKEY_DH) { const DH *dh = EVP_PKEY_get0_DH(pkey); if (dh != nullptr) { keysize = BN_num_bits(DH_get0_p(dh)); } } else if (key_type == EVP_PKEY_EC) { const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey); if (ec != nullptr) { keysize = EC_GROUP_get_degree(EC_KEY_get0_group(ec)); } } EVP_PKEY_free(pkey); return keysize; }
*补充说明:如果后续遇到其他类似的结构体成员访问报错,都可以通过查询OpenSSL 1.1.1版本公开API,找到对应结构体的属性获取接口替换即可。
内容的提问来源于stack exchange,提问作者carraro
相关产品推荐
相关产品推荐

