You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenSSL C库及PEM公钥文件加密短std::string并实现指定函数

实现基于OpenSSL C库的非对称字符串加密函数

首先明确:ECDSA是签名算法,不能直接用于加密短字符串,如果你需要基于椭圆曲线的加密,应该用ECIES(椭圆曲线集成加密方案)。下面的实现基于OpenSSL的EVP高层API,可兼容RSA(含OAEP填充)、ECIES等支持公钥加密的算法,完全匹配你要求的接口。

核心实现步骤

  • 从PEM格式的公钥字符串加载EVP_PKEY对象
  • 创建并初始化加密上下文EVP_PKEY_CTX
  • 计算加密后数据的长度,分配缓冲区
  • 执行加密并将结果写入输出字符串
  • 清理所有OpenSSL资源(必须执行,避免内存泄漏)

完整代码实现

#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <string>
#include <cstring>

bool EncryptString(const std::string& InStr, const std::string& InPublicKey, std::string& OutString) {
    // 若程序未全局初始化OpenSSL,需添加以下两行
    // OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
    // OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);

    // 1. 将PEM公钥字符串转为BIO对象
    BIO* bio = BIO_new_mem_buf(InPublicKey.data(), InPublicKey.size());
    if (!bio) {
        return false;
    }

    // 2. 从BIO加载公钥
    EVP_PKEY* pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
    BIO_free(bio); // 读完公钥即可释放BIO
    if (!pkey) {
        return false;
    }

    // 3. 创建加密上下文,ENGINE传NULL使用默认实现
    EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
    if (!ctx) {
        EVP_PKEY_free(pkey);
        return false;
    }

    // 4. 初始化加密操作
    if (EVP_PKEY_encrypt_init(ctx) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return false;
    }

    // 可选:显式设置RSA OAEP填充(默认即为此填充,更安全)
    // 若需兼容旧系统可改为PKCS#1 v1.5,但不推荐
    if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return false;
    }

    // 5. 计算加密后数据的长度
    size_t out_len = 0;
    if (EVP_PKEY_encrypt(ctx, NULL, &out_len, (const unsigned char*)InStr.data(), InStr.size()) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return false;
    }

    // 6. 分配缓冲区并执行加密
    OutString.resize(out_len);
    if (EVP_PKEY_encrypt(ctx, (unsigned char*)OutString.data(), &out_len, (const unsigned char*)InStr.data(), InStr.size()) <= 0) {
        OutString.clear();
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return false;
    }
    OutString.resize(out_len); // 修正实际加密长度可能小于预估的情况

    // 7. 清理资源
    EVP_PKEY_CTX_free(ctx);
    EVP_PKEY_free(pkey);

    return true;
}

关键说明

  1. OpenSSL初始化:如果程序未全局初始化OpenSSL,必须添加代码中的初始化行,否则可能出现崩溃或逻辑错误。
  2. ECDSA兼容说明:ECDSA本身无法加密,若使用椭圆曲线加密,需提供ECIES格式的公钥,上述代码会自动兼容合法的ECIES公钥。
  3. 长度限制:以2048位RSA密钥为例,OAEP填充下最多可加密245字节,完全满足你100字节以内的需求。
  4. 二进制输出:加密结果为二进制数据,若需可打印字符串(如网络传输),可使用OpenSSL的EVP_Encode系列函数转为Base64格式。

内容的提问来源于stack exchange,提问作者goose_lake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 00:41:04