使用OpenSSL的EVP_RSA_gen生成RSA密钥后,获取原始公钥大小失败求助
问题:调用EVP_PKEY_get_raw_public_key提取RSA公钥失败
我正尝试使用<openssl/evp.h>中的EVP_RSA_gen接口生成RSA密钥对,相关代码如下:
#include <string.h> #include <openssl/rsa.h> #include <openssl/evp.h> #include <openssl/err.h> int main() { EVP_PKEY *pkey = NULL; pkey = EVP_RSA_gen(4096); if (pkey == NULL){ ERR_print_errors_fp(stderr); printf("Key generation failed.\n"); } size_t keyLen; if (EVP_PKEY_get_raw_public_key(pkey, NULL, &keyLen) != 1) { ERR_print_errors_fp(stderr); printf("Key extraction failed.\n"); } return 0; }
但当我按照文档说明调用EVP_PKEY_get_raw_public_key获取原始公钥的大小,操作失败并打印了“Key extraction failed”,且ERR_print_errors_fp未输出任何错误信息。我哪里操作出错了?看起来代码没有问题。
解答
错误原因
EVP_PKEY_get_raw_public_key 函数不支持RSA密钥,它仅针对不需要ASN.1封装的"原始公钥"算法(如椭圆曲线、Ed25519/Ed448等)。RSA公钥默认是以ASN.1 DER格式封装的,因此调用该函数会直接返回失败;同时你的代码未初始化OpenSSL错误栈,导致错误信息无法正常输出。
解决方法
根据需求不同,有两种可行的处理方式:
1. 获取ASN.1编码的标准RSA公钥(通用PEM/DER格式)
如果需要生成通用的RSA公钥格式,使用i2d_PUBKEY函数获取编码后的公钥数据:
// 在生成pkey成功后添加以下代码 unsigned char *pub_key = NULL; int pub_len = i2d_PUBKEY(pkey, &pub_key); if (pub_len > 0) { printf("ASN.1 encoded public key length: %d\n", pub_len); // 使用完后释放内存 OPENSSL_free(pub_key); } else { ERR_print_errors_fp(stderr); printf("Failed to get ASN.1 public key.\n"); }
2. 直接获取RSA的原始模(n)和指数(e)
如果需要直接操作RSA核心参数,先将EVP_PKEY转换为RSA结构,再读取对应字段:
// 在生成pkey成功后添加以下代码 RSA *rsa = EVP_PKEY_get1_RSA(pkey); if (rsa != NULL) { // 获取模的字节长度 size_t n_len = BN_num_bytes(rsa->n); // 获取指数的字节长度 size_t e_len = BN_num_bytes(rsa->e); printf("RSA modulus length: %zu bytes, exponent length: %zu bytes\n", n_len, e_len); // 若需要将模和指数导出为字节数组 unsigned char *n_buf = malloc(n_len); unsigned char *e_buf = malloc(e_len); BN_bn2bin(rsa->n, n_buf); BN_bn2bin(rsa->e, e_buf); // 使用完后释放资源 free(n_buf); free(e_buf); RSA_free(rsa); } else { ERR_print_errors_fp(stderr); printf("Failed to convert EVP_PKEY to RSA.\n"); }
额外建议
记得初始化OpenSSL的算法库和错误栈,否则错误信息可能无法正常输出,在main函数开头添加:
// OpenSSL 1.1.0及以上版本 OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_LOAD_CONFIG, NULL); // 旧版本(如1.0.2)使用以下两行 // OpenSSL_add_all_algorithms(); // ERR_load_crypto_strings();
内容的提问来源于stack exchange,提问作者Dmytro
相关产品推荐
相关产品推荐

