Python生成X25519 DER公钥,C语言OpenSSL解码为32字节公钥失败求助
解决X25519 SubjectPublicKeyInfo格式DER解码为原始32字节公钥的问题
你用Python生成的是SubjectPublicKeyInfo格式的DER数据,这是一个标准ASN.1结构,包含算法标识和公钥内容,不能直接用d2i_ASN1_OCTET_STRING解析,得用OpenSSL针对公钥的专用解析函数处理。
正确的解码步骤
- 使用
d2i_PUBKEY解析DER格式的SubjectPublicKeyInfo,得到EVP_PKEY结构体 - 从
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
相关产品推荐
相关产品推荐

