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

OpenSSL 1.1.1中ED448公钥DER编码失败问题求助

解决ED448公钥编码失败的问题

你踩了OpenSSL 1.1.1对Ed448支持的一个小坑:这个版本里,Ed448(以及同系列的Ed25519)密钥并不兼容传统的i2d_PublicKey接口。i2d_PublicKey是为基于X.509 SubjectPublicKeyInfo结构的DER/PEM编码设计的,但早期OpenSSL对Ed448的支持只实现了原始密钥字节的读写能力,没有适配标准的ASN.1编码逻辑,所以才会抛出“不支持的公钥类型”错误。

更贴合你需求的方案:直接提取原始公钥字节

既然你想要“小巧可移植的字节数组”,那Ed448的原始公钥本身就是最优解——它固定是56字节(对应448位),没有额外的ASN.1包装,体积更小、解析更简单。你可以用EVP_PKEY_get_raw_public_key接口替代i2d_PublicKey,修改后的代码如下:

std::vector<std::vector<uint8_t>> vecs;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED448, NULL);
if (!pctx) {
    ERR_print_errors_fp(stderr);
    // 这里可以加错误处理逻辑,比如return或者抛出异常
    return;
}

if (EVP_PKEY_keygen_init(pctx) <= 0) {
    ERR_print_errors_fp(stderr);
    EVP_PKEY_CTX_free(pctx);
    return;
}

EVP_PKEY* pkey = nullptr;
if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
    ERR_print_errors_fp(stderr);
    EVP_PKEY_CTX_free(pctx);
    return;
}
EVP_PKEY_CTX_free(pctx);

// 获取原始公钥长度,Ed448固定为56字节
size_t pub_key_len = EVP_PKEY_get_size(pkey);
std::vector<uint8_t> pub_key(pub_key_len);

// 提取原始公钥字节到vector中
if (EVP_PKEY_get_raw_public_key(pkey, pub_key.data(), &pub_key_len) <= 0) {
    ERR_print_errors_fp(stderr);
    EVP_PKEY_free(pkey);
    return;
}

vecs.push_back(std::move(pub_key));
EVP_PKEY_free(pkey);

如果必须用DER编码怎么办?

如果你的场景硬性要求DER格式的公钥(比如要嵌入X.509证书),那OpenSSL 1.1.1做不到——Ed448的X.509 SubjectPublicKeyInfo编码支持是在OpenSSL 3.0及以后版本才完善的。你需要升级到Debian stable版本中的OpenSSL 3.0(或更高),升级后i2d_PublicKey就能正常处理Ed448密钥了。

几个关键提醒

  • Ed448的原始公钥长度固定为56字节,私钥是57字节(多一个公钥字节用于性能优化),你也可以直接写死这个长度来分配缓冲区,避免调用EVP_PKEY_get_size。
  • 一定要检查OpenSSL所有API的返回值(大部分接口返回<=0表示失败),不然很容易出现空指针或者内存越界的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:55:50