OpenSSL v1.1.0f设置RSA密钥时出现「不完整类型」错误求助
解决OpenSSL 1.1.0f中RSA结构体“dereferencing pointer to incomplete type”错误
这个问题我之前适配OpenSSL 1.1.x版本时也碰到过,根源很明确:OpenSSL从1.1.0版本开始,将RSA、EVP等核心结构体改成了不透明类型(opaque type),目的是提升API的封装性和向后兼容性,你不能再像旧版本那样直接通过keys->n、keys->e这种方式访问结构体内部成员了,这就是你触发错误的原因。
下面是具体的解决步骤和代码示例:
1. 使用OpenSSL提供的专用函数设置密钥参数
OpenSSL 1.1.0+提供了一系列替代直接访问结构体的API,用来设置RSA的公/私钥参数:
- 设置公钥(n、e):使用
RSA_set0_key()或RSA_set0_pubkey() - 设置私钥因子(p、q):使用
RSA_set0_factors() - 设置私钥CRT参数:使用
RSA_set0_crt_params()
以你的加密函数为例,修改后的正确代码如下:
#include <openssl/rsa.h> #include <openssl/bn.h> // 假设byte是你定义的unsigned char别名 int rsa_encrypt(byte *in, size_t in_len, byte *out, const char *n_hex, const char *e_hex, char padding){ int err = -1; RSA *keys = RSA_new(); if (!keys) { return err; } BIGNUM *n = NULL, *e = NULL; // 将十六进制字符串转换为BIGNUM if (!BN_hex2bn(&n, n_hex) || !BN_hex2bn(&e, e_hex)) { BN_free(n); BN_free(e); RSA_free(keys); return err; } // 使用RSA_set0_key设置公钥参数:最后一个参数d传NULL(公钥不需要私钥指数) if (!RSA_set0_key(keys, n, e, NULL)) { // 如果设置失败,需要手动释放BIGNUM BN_free(n); BN_free(e); RSA_free(keys); return err; } // 注意:调用RSA_set0_key后,OpenSSL会接管n和e的内存,后续不需要手动free // 处理填充模式 int pad_mode; switch(padding){ case 'o': pad_mode = RSA_PKCS1_OAEP_PADDING; break; case 'p': pad_mode = RSA_PKCS1_PADDING; break; default: pad_mode = RSA_NO_PADDING; break; } // 执行公钥加密 int out_len = RSA_public_encrypt((int)in_len, in, out, keys, pad_mode); if (out_len > 0) { err = 0; } // 只需要释放RSA结构体,内部的BIGNUM会被自动清理 RSA_free(keys); return err; }
2. 确认编译和链接配置
确保你的代码包含了正确的头文件#include <openssl/rsa.h>,并且编译时链接OpenSSL的crypto库,比如使用GCC编译时加上参数:
gcc your_code.c -o your_program -lcrypto
额外注意事项
- 如果需要设置私钥的p、q、d等参数,同样要用对应的
RSA_set0_*函数,比如RSA_set0_factors(keys, p, q)来设置素因子p和q。 - 所有通过
BN_hex2bn创建的BIGNUM,一旦通过RSA_set0_*传递给RSA结构体,就不需要手动调用BN_free了,RSA_free会自动清理这些内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Faulst
相关产品推荐
相关产品推荐

