C++如何使用OpenSSL实现RSA加密_C++网络安全传输代码实例【方案】

2次阅读

openssl c++封装无官方api,需手动管理bio/rsa生命周期;密钥加载须用pem_read_bio_*配对bio_new_mem_buf();rsa加密明文上限为rsa_size(rsa)-11;密钥写入前须chmod 600防泄露;错误队列需循环err_get_error()清空。

C++如何使用OpenSSL实现RSA加密_C++网络安全传输代码实例【方案】

OpenSSL 的 C++ 封装本身不存在官方 API,所谓“C++ 使用 OpenSSL”实际是用 C 风格的 OpenSSL 库(libssllibcrypto)在 C++ 环境中调用,需手动管理资源、处理错误、规避裸指针误释放——这不是语法问题,而是内存与生命周期问题。

如何正确加载 RSA 密钥并避免 SEGFAULTnullptr 解引用

OpenSSL 1.1.1+ 后,RSA 结构体被 opaque 化,不能直接访问成员;密钥加载必须通过 PEM_read_bio_RSAPrivateKey / PEM_read_bio_RSAPublicKey,且必须配对使用 BIO 生命周期管理。

  • BIO* 必须用 BIO_new_mem_buf() 创建,传入 PEM 字符串地址和长度(不能传 std::String::c_str() 后不指定长度,否则遇到 会截断)
  • 私钥加载失败常见原因是密码不匹配或格式非 PKCS#1(如用了 PKCS#8),此时返回 nullptr,但不会报错——必须用 ERR_get_error() 检查
  • 成功加载后,RSA* 对象必须用 RSA_free() 释放,不能用 delete;若封装成 RAII 类,析构函数里必须判空再调 RSA_free

为什么 RSA_public_encrypt() 返回 -1 且 ERR_get_error() 显示 rsa routines:RSA_padding_add_PKCS1_type_2:data too large for key size

RSA 加密明文长度受限于密钥长度和填充方式。PKCS#1 v1.5 填充固定占用至少 11 字节,因此最大明文长度 = RSA_size(rsa) - 11。例如 2048 位密钥,RSA_size() 返回 256 字节,最多加密 245 字节。

  • 不要试图分块调用 RSA_public_encrypt:它不是流式接口,每次调用都需完整填充,无法接力
  • 真实场景应改用混合加密:用 RSA 加密一个随机 AES 密钥,再用 AES 加密原始数据
  • 若坚持纯 RSA,必须提前 if (plaintext_len > RSA_size(rsa) - 11) { /* reject */ },否则返回 -1 且输出缓冲区内容未定义

如何安全生成密钥并写入 PEM 文件(避免权限泄露)

OpenSSL 不自动设置文件权限,PEM_write_RSAPrivateKey 直接写磁盘可能导致私钥被其他用户读取。

立即学习C++免费学习笔记(深入)”;

  • 生成密钥必须用 RSA_generate_key_ex()(OpenSSL 1.1.0+ 推荐),而非已废弃的 RSA_generate_key()
  • 写私钥前先用 umask(077) 临时收紧权限,或写入 /tmp 后用 chmod 600 显式设置(windows 下忽略)
  • 写入时若需密码保护,cb 参数不能为 nullptr;推荐用 PEM_write_enc_RSAPrivateKey 并传入 EVP_des_ede3_cbc()算法,密码由回调函数提供
  • 公钥可无密码导出,但务必确认 PEM_write_RSAPublicKey(写 PKCS#1 格式)还是 PEM_write_PUBKEY(写 SubjectPublicKeyInfo,兼容性更好)

最易被忽略的是错误队列残留:OpenSSL 错误是线程局部的,但每个函数调用可能压入多条错误。一次 ERR_get_error() 只取一条,连续调用直到返回 0 才清空。调试时若只查一次,会漏掉根本原因。

text=ZqhQzanResources