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

使用OpenSSL的EVP_KEY获取RSA原始私钥失败求助

问题分析与解决方案

核心问题

你的代码存在三个关键错误,导致私钥无法正确获取和打印:

  1. 错误使用EVP_PKEY_get_raw_private_key
    该函数仅支持EC、Ed25519等算法的"原始私钥"格式,RSA私钥是ASN.1 DER编码的结构化数据,无法通过此函数提取。调用该函数会直接失败(返回0),因此private_key数组始终未被写入。

  2. 内存分配长度错误
    RSA私钥的DER编码长度远大于KEY_LENGTH(1024位RSA的DER私钥约1KB),你用KEY_LENGTH +1分配的内存完全不足,且未先查询实际所需长度。

  3. 二进制数据用字符串方式打印
    私钥是二进制字节序列,包含大量不可打印字符和0值字节,用printf("%s")会在第一个0字节处截断,无法完整输出。

修正后的代码

方案1:输出PEM格式私钥(最常用,可读性强)

直接通过OpenSSL的PEM函数将私钥输出为Base64编码的文本格式:

#include <openssl/evp.h>
#include <openssl/pem.h>
#include <stdio.h>
#include <stdlib.h>

#define KEY_LENGTH 1024

int main() {
    EVP_PKEY *pkey = EVP_RSA_gen(KEY_LENGTH);
    if (pkey == NULL) {
        fprintf(stderr, "error: rsa gen\n");
        ERR_print_errors_fp(stderr);
        return 1;
    }

    // 输出PEM格式私钥到标准输出
    if (!PEM_write_PrivateKey(stdout, pkey, NULL, NULL, 0, NULL, NULL)) {
        fprintf(stderr, "error: write private key\n");
        ERR_print_errors_fp(stderr);
        EVP_PKEY_free(pkey);
        return 1;
    }

    EVP_PKEY_free(pkey);
    return 0;
}

方案2:获取DER编码二进制私钥并以十六进制打印

若需获取原始二进制私钥并查看,先查询长度再分配内存,最后以十六进制格式打印:

#include <openssl/evp.h>
#include <openssl/asn1.h>
#include <stdio.h>
#include <stdlib.h>

#define KEY_LENGTH 1024

int main() {
    EVP_PKEY *pkey = EVP_RSA_gen(KEY_LENGTH);
    if (pkey == NULL) {
        fprintf(stderr, "error: rsa gen\n");
        ERR_print_errors_fp(stderr);
        return 1;
    }

    // 第一步:获取DER编码私钥的长度
    int pkey_len = i2d_PrivateKey(pkey, NULL);
    if (pkey_len <= 0) {
        fprintf(stderr, "error: get private key length\n");
        ERR_print_errors_fp(stderr);
        EVP_PKEY_free(pkey);
        return 1;
    }

    // 分配内存
    unsigned char *private_key = malloc(pkey_len);
    if (!private_key) {
        fprintf(stderr, "error: malloc failed\n");
        EVP_PKEY_free(pkey);
        return 1;
    }

    // 第二步:将私钥编码到内存中
    unsigned char *ptr = private_key;
    i2d_PrivateKey(pkey, &ptr);

    // 以十六进制打印私钥
    printf("DER私钥(十六进制):\n");
    for (int i = 0; i < pkey_len; i++) {
        printf("%02x ", private_key[i]);
        if ((i + 1) % 16 == 0) printf("\n");
    }
    printf("\n");

    free(private_key);
    EVP_PKEY_free(pkey);
    return 0;
}

额外注意事项

  • 所有OpenSSL函数调用必须检查返回值,比如EVP_PKEY_get_raw_private_key返回0表示失败,你之前未做错误检查,导致无法发现函数调用失败的问题。
  • 记得释放EVP_PKEY和分配的内存,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Vladouch

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 19:05:24