如何用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; }
关键说明
- OpenSSL初始化:如果程序未全局初始化OpenSSL,必须添加代码中的初始化行,否则可能出现崩溃或逻辑错误。
- ECDSA兼容说明:ECDSA本身无法加密,若使用椭圆曲线加密,需提供ECIES格式的公钥,上述代码会自动兼容合法的ECIES公钥。
- 长度限制:以2048位RSA密钥为例,OAEP填充下最多可加密245字节,完全满足你100字节以内的需求。
- 二进制输出:加密结果为二进制数据,若需可打印字符串(如网络传输),可使用OpenSSL的
EVP_Encode系列函数转为Base64格式。
内容的提问来源于stack exchange,提问作者goose_lake
相关产品推荐
相关产品推荐

