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

如何将明文公钥转为DER格式?含OpenSSL及i2d_PUBKEY代码疑问

OpenSSL公钥转DER格式实操解答

问题1:如何通过OpenSSL将明文公钥转换为DER格式?

有两种常用实现方式:命令行工具快速转换,或C代码集成处理。

命令行方式

针对本地PEM格式公钥文件,直接执行openssl命令:

# RSA公钥转换
openssl rsa -in public_key.pem -pubin -outform der -out public_key.der

# EC公钥转换(示例中的密钥为ECC类型)
openssl ec -in public_key.pem -pubin -outform der -out public_key.der

参数说明:

  • -pubin:指定输入文件为公钥
  • -outform der:设置输出格式为DER编码
  • -out:指定输出文件路径

C代码基础方式

若需在程序中处理内存中的PEM公钥,核心步骤为解析PEM到密钥结构体,再序列化为DER格式,具体逻辑可参考问题2的完整示例。


问题2:用i2d_PUBKEY实现公钥转DER编码的具体操作

结合你提供的代码片段,以下是完整可运行的实现,包含PEM公钥解析、i2d_PUBKEY序列化及资源清理的完整流程:

#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/bio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 模拟获取PEM格式公钥的函数
void get_pubkey_function(uint8_t **pubkey, size_t *len) {
    const char *pem_content = "-----BEGIN PUBLIC KEY-----\n"
                             "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+GmnZ1UZqKfa81Yh0CG6huQPhYON\n"
                             "Q0W7AE4whuX+oUOg+BewYSOLUwj5zfwRB3i7T07HoltPfAOYeHI57Oe7jA==\n"
                             "-----END PUBLIC KEY-----";
    *len = strlen(pem_content);
    *pubkey = (uint8_t *)malloc(*len + 1);
    if (*pubkey) {
        memcpy(*pubkey, pem_content, *len + 1);
    }
}

int main() {
    uint8_t *pem_pubkey = NULL;
    size_t pem_len = 0;
    EVP_PKEY *pkey = NULL;
    uint8_t *der_pubkey = NULL;
    int der_len = 0;

    // 获取PEM格式公钥
    get_pubkey_function(&pem_pubkey, &pem_len);
    if (!pem_pubkey) {
        fprintf(stderr, "获取公钥失败\n");
        return EXIT_FAILURE;
    }

    // 创建BIO对象读取内存中的PEM数据
    BIO *bio = BIO_new_mem_buf(pem_pubkey, pem_len);
    if (!bio) {
        fprintf(stderr, "创建BIO缓冲区失败\n");
        free(pem_pubkey);
        return EXIT_FAILURE;
    }

    // 解析PEM公钥到EVP_PKEY通用密钥结构体
    pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
    BIO_free(bio);
    free(pem_pubkey);
    if (!pkey) {
        fprintf(stderr, "解析PEM公钥失败\n");
        return EXIT_FAILURE;
    }

    // 第一步:调用i2d_PUBKEY获取DER数据长度(传入NULL指针)
    der_len = i2d_PUBKEY(pkey, NULL);
    if (der_len <= 0) {
        fprintf(stderr, "计算DER数据长度失败\n");
        EVP_PKEY_free(pkey);
        return EXIT_FAILURE;
    }

    // 分配内存存储DER编码数据
    der_pubkey = (uint8_t *)malloc(der_len);
    if (!der_pubkey) {
        fprintf(stderr, "内存分配失败\n");
        EVP_PKEY_free(pkey);
        return EXIT_FAILURE;
    }

    // 第二步:序列化EVP_PKEY到DER格式内存
    uint8_t *write_ptr = der_pubkey;
    i2d_PUBKEY(pkey, &write_ptr);

    // 此时der_pubkey即为DER编码的公钥,der_len为其字节长度
    printf("DER编码公钥长度:%d字节\n", der_len);

    // 资源清理:释放所有分配的内存和OpenSSL结构体
    free(der_pubkey);
    EVP_PKEY_free(pkey);

    return EXIT_SUCCESS;
}

核心逻辑说明

  • PEM解析:通过BIO_new_mem_buf将内存中的PEM字符串包装为BIO输入流,再用PEM_read_bio_PUBKEY解析为OpenSSL通用密钥结构体EVP_PKEY,该结构体支持RSA、EC等多种密钥类型。
  • i2d_PUBKEY使用要点:
    1. 首次调用传入NULL作为第二个参数,函数返回DER数据的总长度,用于提前分配足够内存。
    2. 二次调用传入指向分配好内存的指针地址(&write_ptr),函数会将DER数据写入内存,并自动移动指针到数据末尾。
  • 资源管理:所有OpenSSL创建的结构体(EVP_PKEY、BIO)必须调用对应free函数释放,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 11:40:50