C/C++中如何使用OpenSSL生成符合X.509规范的DER编码公钥
错误根源
你当前的实现误导出了完整X509证书的DER编码,而Minecraft协议要求的是SubjectPublicKeyInfo(SPKI)结构的公钥DER编码,两者结构不匹配导致客户端解析公钥失败。
你使用的i2d_X509接口会导出包含证书版本、颁发者、有效期等额外字段的完整证书数据,这些内容是协议不需要的,客户端仅会按SPKI结构解析公钥,因此抛出重构失败错误。
正确实现方案
你不需要创建X509对象,直接使用OpenSSL提供的i2d_PUBKEY接口即可从EVP_PKEY结构导出符合要求的SPKI格式DER公钥,修改后的代码逻辑如下:
RSA* rsa = RSA_new(); if (!rsa) return false; BIGNUM* exponent = BN_new(); if (!exponent) { RSA_free(rsa); return false; } EVP_PKEY* pkey = EVP_PKEY_new(); if (!pkey) { RSA_free(rsa); BN_free(exponent); return false; } BN_set_word(exponent, 65537); RSA_generate_key_ex(rsa, 1024, exponent, NULL); EVP_PKEY_set1_RSA(pkey, rsa); // 正确导出SPKI格式DER公钥 std::vector<uint8_t> derPublicKey; { // 先查询所需缓冲区大小 int keyLength = i2d_PUBKEY(pkey, NULL); if (keyLength <= 0) { RSA_free(rsa); BN_free(exponent); EVP_PKEY_free(pkey); return false; } derPublicKey.resize(keyLength); uint8_t* keyPtr = derPublicKey.data(); // 写入DER编码数据 i2d_PUBKEY(pkey, &keyPtr); } // 释放资源逻辑和原有一致 RSA_free(rsa); BN_free(exponent); EVP_PKEY_free(pkey);
验证说明
1024位RSA公钥的SPKI结构DER编码长度通常在140字节左右,你可以输出导出后的derPublicKey长度做初步校验,若长度大于200字节则说明导出逻辑仍有问题。
内容的提问来源于stack exchange,提问作者CryptoNewbie
相关产品推荐
相关产品推荐

