You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 20:11:27