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

Python生成X25519 DER公钥,C语言OpenSSL解码为32字节公钥失败求助

解决X25519 SubjectPublicKeyInfo格式DER解码为原始32字节公钥的问题

你用Python生成的是SubjectPublicKeyInfo格式的DER数据,这是一个标准ASN.1结构,包含算法标识和公钥内容,不能直接用d2i_ASN1_OCTET_STRING解析,得用OpenSSL针对公钥的专用解析函数处理。

正确的解码步骤

  1. 使用d2i_PUBKEY解析DER格式的SubjectPublicKeyInfo,得到EVP_PKEY结构体
  2. 从EVP_PKEY中提取X25519的原始32字节公钥

完整C代码示例

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

int decode_x25519_der_to_raw(const unsigned char* der_data, size_t der_len, unsigned char** raw_key, size_t* raw_len) {
    *raw_key = NULL;
    *raw_len = 0;

    // 解析SubjectPublicKeyInfo格式的DER数据
    const unsigned char* ptr = der_data;
    EVP_PKEY* pkey = d2i_PUBKEY(NULL, &ptr, der_len);
    if (!pkey) {
        fprintf(stderr, "Failed to parse DER as SubjectPublicKeyInfo\n");
        return 1;
    }

    // 验证是否为X25519公钥
    if (EVP_PKEY_id(pkey) != EVP_PKEY_X25519) {
        fprintf(stderr, "Not an X25519 public key\n");
        EVP_PKEY_free(pkey);
        return 1;
    }

    // 提取原始32字节公钥(OpenSSL 1.1.0+支持)
    size_t key_len = EVP_PKEY_get_raw_public_key(pkey, NULL, 0);
    if (key_len != 32) {
        fprintf(stderr, "Unexpected X25519 public key length\n");
        EVP_PKEY_free(pkey);
        return 1;
    }

    *raw_key = (unsigned char*)OPENSSL_malloc(key_len);
    if (!*raw_key) {
        fprintf(stderr, "Memory allocation failed\n");
        EVP_PKEY_free(pkey);
        return 1;
    }

    if (EVP_PKEY_get_raw_public_key(pkey, *raw_key, key_len) != key_len) {
        fprintf(stderr, "Failed to extract raw public key\n");
        OPENSSL_free(*raw_key);
        EVP_PKEY_free(pkey);
        return 1;
    }
    *raw_len = key_len;

    // 释放资源
    EVP_PKEY_free(pkey);
    return 0;
}

// 测试用例
int main() {
    // 替换为你实际的44字节DER数据
    unsigned char x25519_public_der[] = { /* 你的DER字节数组 */ };
    size_t der_len = sizeof(x25519_public_der);

    unsigned char* raw_key;
    size_t raw_len;

    if (decode_x25519_der_to_raw(x25519_public_der, der_len, &raw_key, &raw_len) == 0) {
        printf("Extracted raw X25519 public key (32 bytes):\n");
        for (size_t i = 0; i < raw_len; i++) {
            printf("%02x ", raw_key[i]);
        }
        printf("\n");
        OPENSSL_free(raw_key);
    }

    return 0;
}

关键说明

  • d2i_PUBKEY是OpenSSL专门用于解析SubjectPublicKeyInfo格式的函数,会自动识别算法类型(这里是X25519)
  • EVP_PKEY_get_raw_public_key直接提取原始公钥字节,无需手动处理ASN.1结构的嵌套
  • 必须验证公钥类型和长度,避免解析错误数据
  • 所有分配的内存要记得释放,防止内存泄漏

旧版本OpenSSL兼容(低于1.1.0)

如果你的OpenSSL版本低于1.1.0,可以用EVP_PKEY_get0_X25519_public_key替代EVP_PKEY_get_raw_public_key:

const unsigned char* raw_ptr = EVP_PKEY_get0_X25519_public_key(pkey);
if (!raw_ptr) {
    // 错误处理逻辑
}
// 手动复制raw_ptr指向的32字节到自定义缓冲区

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 20:52:03