EC私钥创建异常:PEM格式文件生成错误原因排查求助
问题:OpenSSL生成EC密钥转PEM格式出错,私钥有效性存疑
我用以下代码创建EC_KEY,但转换为PEM格式文件时得到异常结果,不确定私钥是否正确,想找出问题所在:
#include <openssl/ec.h> #include <openssl/evp.h> #include <openssl/pem.h> int main(){ EC_KEY *ec_key = EC_KEY_new(); EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1); if (EC_KEY_set_group(ec_key, group) != 1) { printf("SyncServer : Failed to set EC group\n"); return 0; } if (EC_KEY_generate_key(ec_key) != 1) { printf("SyncServer : Failed to generate EC key\n"); return 0; } EVP_PKEY *evp_key = EVP_PKEY_new(); if (EVP_PKEY_set1_EC_KEY(evp_key, ec_key) != 1) { printf("failed to get ec_key!\n"); return 0; } FILE *file = fopen("ec_private_key.pem", "w"); if (file != NULL) { if (PEM_write_PrivateKey(file, evp_key, NULL, NULL, 0, NULL, NULL) != 1) { printf("Failed to create file\n"); return 0; } fclose(file); } // Cleanup EVP_PKEY_free(evp_key); return 0; }
生成的PEM结果:
-----BEGIN PRIVATE KEY----- MIICDAIBADCCAWQGByqGSM49AgEwggFXAgEBMDwGByqGSM49AQECMQD///////// /////////////////////////////////v////8AAAAAAAAAAP////8wewQw//// //////////////////////////////////////7/////AAAAAAAAAAD////8BDCz MS+n4j7n5JiOBWvj+C0ZGB2cbv6BQRIDFAiPUBOHWsZWOY2KLtGdKoXI7dPsKu8D FQCjNZJqoxmieh0AiWpnc6SCes2scwRhBKqHyiK+iwU3jrHHHvMgrXRuHTtii6eb mFn3QeCCVCo4VQLyXb9VKWw6VF44cnYKtzYX3kqWJixvXZ6Yv5KS3Cn49B29KJoU fOnaMRO18LjACmCxzh1+gZ16Qx18kOoOXwIxAP////////////////////////// /////8djTYH0Ny3fWBoNskiwp3rs7BlqzMUpcwIBAQSBnjCBmwIBAQQw8q0GAqh4 BeAZSu7AzUanABFjIvyVlsJN56M21Ora7O4YbPn7Qb64bTJQjwQSNeiRoWQDYgAE qdajmPcqDLjcO5MdpwQQ8IbgCa4LthXJC/ERemGVT8+VJ/ZOFjJe9JvH2al/Sz3R zkiQ38dG7a8cseEEvLDtHhQFnzROBfeZzybLvcZHzEmI5kTZ6mlLQz7NQl7fZM+2 -----END PRIVATE KEY-----
问题分析与修复方案
1. 资源泄漏问题
代码存在两处未正确释放的资源,虽不直接导致PEM异常,但会引发内存泄漏:
EC_GROUP *group创建后,仅关联到EC_KEY但未调用EC_GROUP_free(group)释放EC_KEY *ec_key关联到EVP_PKEY后,未调用EC_KEY_free(ec_key)释放
2. PEM格式与输出完整性问题
- 你使用的
PEM_write_PrivateKey输出的是PKCS#8通用私钥格式(开头为-----BEGIN PRIVATE KEY-----),这是标准格式,但如果需要EC密钥专用格式(开头为-----BEGIN EC PRIVATE KEY-----),应改用PEM_write_ECPrivateKey函数,兼容性更好。 - 你提供的PEM结果末尾明显截断,大概率是文件写入时未正常完成,可通过添加错误日志或验证文件完整性排查。
3. 私钥有效性验证方法
用OpenSSL命令行直接验证生成的私钥:
# 验证PKCS#8格式私钥 openssl pkcs8 -in ec_private_key.pem -nocrypt -text # 若改用EC专用格式,用以下命令 openssl ec -in ec_private_key.pem -text -noout
如果命令能正常输出曲线参数、私钥值和公钥值,说明私钥本身有效。
修复后的完整代码
#include <openssl/ec.h> #include <openssl/evp.h> #include <openssl/pem.h> #include <stdio.h> int main(){ EC_KEY *ec_key = EC_KEY_new(); if (!ec_key) { printf("SyncServer : Failed to create EC_KEY\n"); return 1; } EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1); if (!group) { printf("SyncServer : Failed to create EC_GROUP\n"); EC_KEY_free(ec_key); return 1; } if (EC_KEY_set_group(ec_key, group) != 1) { printf("SyncServer : Failed to set EC group\n"); EC_GROUP_free(group); EC_KEY_free(ec_key); return 1; } // 关联后释放group,EC_KEY内部会持有引用 EC_GROUP_free(group); if (EC_KEY_generate_key(ec_key) != 1) { printf("SyncServer : Failed to generate EC key\n"); EC_KEY_free(ec_key); return 1; } // 方案1:写入EC专用私钥格式 FILE *ec_file = fopen("ec_private_key_ec.pem", "w"); if (ec_file) { if (PEM_write_ECPrivateKey(ec_file, ec_key, NULL, NULL, 0, NULL, NULL) != 1) { printf("Failed to write EC private key\n"); } fclose(ec_file); } // 方案2:通过EVP_PKEY写入PKCS#8格式(原方案) EVP_PKEY *evp_key = EVP_PKEY_new(); if (evp_key) { if (EVP_PKEY_set1_EC_KEY(evp_key, ec_key) == 1) { FILE *p8_file = fopen("ec_private_key_pkcs8.pem", "w"); if (p8_file) { if (PEM_write_PrivateKey(p8_file, evp_key, NULL, NULL, 0, NULL, NULL) != 1) { printf("Failed to write PKCS#8 private key\n"); } fclose(p8_file); } } else { printf("failed to associate EC_KEY with EVP_PKEY!\n"); } EVP_PKEY_free(evp_key); } else { printf("Failed to create EVP_PKEY\n"); } // 释放EC_KEY EC_KEY_free(ec_key); return 0; }
内容的提问来源于stack exchange,提问作者Ajith Nair
相关产品推荐
相关产品推荐

