使用OpenSSL时BN_hex2bn与BN_bn2hex结果不匹配的问题求助
排查OpenSSL中BN_bn2hex与BN_hex2bn转换不匹配的问题
我之前也踩过OpenSSL这类BIGNUM转换的坑,咱们一步步拆解可能的问题:
1. 先检查BN_hex2bn的调用姿势是否正确
这是最容易出错的点!BN_hex2bn的第一个参数要求传入**BIGNUM类型的指针(也就是指针的地址),用来让函数内部分配内存并返回转换结果。如果直接传单指针,肯定会出问题。
错误示例:
BIGNUM *n_new; BN_hex2bn(n_new, n_s.c_str()); // 这里传的是单指针,完全错误!
正确调用方式:
BIGNUM *n_new = nullptr; // 必须传指针的地址,让函数内部完成内存分配 int ret = BN_hex2bn(&n_new, n_s.c_str()); if (ret == 0 || n_new == nullptr) { std::cerr << "BN_hex2bn转换n失败" << std::endl; // 别忘了释放已分配的资源 return -1; }
2. 确认字符串是否被完整保存且正确释放内存
你代码里e_s = std::string(e_b...看起来是截断了,实际代码里要确保BN_bn2hex返回的char*被完整复制到std::string中。另外,BN_bn2hex返回的内存是OpenSSL分配的,用完必须用OPENSSL_free()释放,不然会造成内存泄漏:
char *n_b = BN_bn2hex(rsa->n); n_s = std::string(n_b); OPENSSL_free(n_b); // 这步绝对不能忘!
3. 别用指针地址判断数值是否匹配
你之前直接cout << rsa->n打印的是BIGNUM对象的指针地址,不是实际数值!要验证转换前后是否一致,必须用OpenSSL提供的BN_cmp()函数:
// 假设n_new是转换后的BIGNUM if (BN_cmp(rsa->n, n_new) == 0) { std::cout << "n转换后数值完全匹配" << std::endl; } else { std::cout << "n转换后数值不匹配" << std::endl; // 可以分别打印十六进制字符串对比差异 char *n_new_hex = BN_bn2hex(n_new); std::cout << "原n的十六进制: " << n_s << std::endl; std::cout << "转换后n的十六进制: " << n_new_hex << std::endl; OPENSSL_free(n_new_hex); }
4. 检查OpenSSL版本兼容性
某些旧版本的OpenSSL(比如1.0.0之前的版本)可能存在BN相关函数的bug,如果你的版本比较老,建议升级到稳定版本(比如1.1.1系列或者3.x系列)。
最后给你一个完整的可运行示例,涵盖生成、转换、验证的全流程:
#include <iostream> #include <string> #include <openssl/rsa.h> #include <openssl/bn.h> #include <openssl/crypto.h> int main() { int kBits = 2048; unsigned long kExp = RSA_F4; // 常用的65537 // 生成RSA密钥 RSA *rsa = RSA_generate_key(kBits, kExp, nullptr, nullptr); if (rsa == nullptr) { std::cerr << "RSA_generate_key生成密钥失败" << std::endl; return -1; } // BIGNUM转十六进制字符串并释放临时内存 char *n_b = BN_bn2hex(rsa->n); char *d_b = BN_bn2hex(rsa->d); char *e_b = BN_bn2hex(rsa->e); std::string n_s(n_b); std::string d_s(d_b); std::string e_s(e_b); OPENSSL_free(n_b); OPENSSL_free(d_b); OPENSSL_free(e_b); // 十六进制字符串转回BIGNUM BIGNUM *n_new = nullptr; BIGNUM *d_new = nullptr; BIGNUM *e_new = nullptr; if (BN_hex2bn(&n_new, n_s.c_str()) == 0 || n_new == nullptr) { std::cerr << "n转换失败" << std::endl; RSA_free(rsa); return -1; } if (BN_hex2bn(&d_new, d_s.c_str()) == 0 || d_new == nullptr) { std::cerr << "d转换失败" << std::endl; RSA_free(rsa); BN_free(n_new); return -1; } if (BN_hex2bn(&e_new, e_s.c_str()) == 0 || e_new == nullptr) { std::cerr << "e转换失败" << std::endl; RSA_free(rsa); BN_free(n_new); BN_free(d_new); return -1; } // 验证转换结果 if (BN_cmp(rsa->n, n_new) == 0 && BN_cmp(rsa->d, d_new) == 0 && BN_cmp(rsa->e, e_new) == 0) { std::cout << "所有密钥参数转换后均匹配!" << std::endl; } else { std::cout << "转换后数值不匹配,请检查字符串完整性或转换逻辑" << std::endl; } // 释放所有资源 RSA_free(rsa); BN_free(n_new); BN_free(d_new); BN_free(e_new); return 0; }
内容的提问来源于stack exchange,提问作者Nash
相关产品推荐
相关产品推荐

