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

使用OpenSSL加解密字符串:缓冲区调整、Base64转换及代码异常

AES加密问题解析与代码修正

问题描述

  • 不清楚如何调整存储加解密字符串的cipher_buf和buffer的大小
  • 不知道如何将加密后的buffer转换为Base64,是否需要第三方库还是OpenSSL自带API可用
  • 当前代码存在异常:执行最后一次buffer.append后,Visual Studio调试器显示buffer内容为空,但buffer.size()返回值为31

原代码

#include <openssl/aes.h>
#include <openssl/evp.h>
#include <Windows.h>
#include <string>

void decryptOrEncrypt()
{
    bool encrypt = true;

    std::string str = "testing testing";

    const int MAX_BUFFER_SIZE = str.length();

    int out_len;
    EVP_CIPHER_CTX * ctx = EVP_CIPHER_CTX_new();

    std::string key = "abcdabcdabcdabcd";
    std::string iv = "abcdabcdabcdabcd";

    size_t len = key.size();
    byte* keyPtr = (byte*)key.data();
    byte* ivPtr = (byte*)iv.data();

    EVP_CipherInit(ctx, EVP_aes_128_cbc(), keyPtr, ivPtr , encrypt);
    int blocksize = EVP_CIPHER_CTX_block_size(ctx);
    std::string cipher_buf;
    cipher_buf.resize(MAX_BUFFER_SIZE + blocksize);

    std::string buffer;
    buffer.resize(MAX_BUFFER_SIZE);

    EVP_CipherUpdate(ctx, reinterpret_cast<uchar *>(cipher_buf.data())
        , &out_len, reinterpret_cast<uchar *>(str.data()), str.length());
    buffer.append(cipher_buf.data(), out_len);

    EVP_CipherFinal(ctx, reinterpret_cast<uchar *>(cipher_buf.data()), &out_len);
    buffer.append(cipher_buf.data(), out_len);
    
    auto s = buffer.size(); 

    //std::string test = base64_encode(buffer.c_str(), buffer.length());
    //std::string test = base64_decode(buffer);
    EVP_CIPHER_CTX_free(ctx);

    return;
}


INT main(INT argc, PCHAR* argv)
{
    decryptOrEncrypt();
}

问题解决与优化

1. 解决buffer显示为空但size异常的问题

你的代码中buffer.resize(MAX_BUFFER_SIZE)会先给buffer填充14个空字符('\0',原字符串长度为14),后续两次append又添加了17个加密后的数据,最终buffer的前14位都是'\0',调试器通常会在第一个'\0'处停止显示内容,所以看起来为空,但实际size是正确的14+17=31。

修正方法:初始化buffer时不要提前resize,直接用空字符串起步,仅通过append添加有效数据:

std::string buffer; // 初始为空,无需提前分配空间

2. 调整cipher_buf与buffer的大小

  • cipher_buf:作为单次加密的临时输出缓冲区,只需满足单次输出的最大可能长度。EVP_CipherUpdate的单次输出最大长度为输入长度 + 块大小,你当前设置的MAX_BUFFER_SIZE + blocksize完全足够;如果处理的字符串不大,也可以直接固定设为1024这类足够大的数值,避免动态计算。
  • buffer:std::string的append方法会自动扩容,无需提前预设大小。如果想优化性能减少扩容次数,可以提前预估加密后的总长度(AES-CBC加密后长度为原长度向上取整到块大小的整数倍,最多比原长度多一个块大小),用reserve预分配空间:
buffer.reserve(str.length() + blocksize);

3. 加密后转Base64:使用OpenSSL自带API

OpenSSL自带完整的Base64编解码工具,无需依赖第三方库。可以使用EVP_EncodeBlock(适合小数据量)或EVP_EncodeInit_ex/EVP_EncodeUpdate/EVP_EncodeFinal(适合大数据流)。

示例:加密后转Base64

在你的代码中,加密完成后添加以下代码即可:

// 计算Base64输出的最大长度
int base64_max_len = EVP_ENCODE_LENGTH(buffer.size());
std::string base64_result(base64_max_len, '\0');

// 执行Base64编码,EVP_EncodeBlock会自动添加换行符
int actual_len = EVP_EncodeBlock(
    reinterpret_cast<unsigned char*>(base64_result.data()),
    reinterpret_cast<const unsigned char*>(buffer.data()),
    buffer.size()
);

// 去掉末尾自动添加的换行符(如果不需要)
if (base64_result.back() == '\n') {
    base64_result.pop_back();
    actual_len--;
}

// 调整字符串到实际长度
base64_result.resize(actual_len);

Base64解码示例(如果需要)

// 假设base64_str是要解码的Base64字符串
std::string decoded_data;
decoded_data.reserve(base64_str.size() * 3 / 4); // 预估解码后的最大长度

int out_len;
EVP_DecodeBlock(
    reinterpret_cast<unsigned char*>(decoded_data.data()),
    reinterpret_cast<const unsigned char*>(base64_str.data()),
    base64_str.size()
);

// 注意:需要根据实际情况调整解码后的长度,通常需要去掉填充的'='

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 04:20:23