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

C++ EVP_Cipher AES-256-CBC加密文件后OpenSSL命令行解密失败求助

问题分析:AES-256-CBC加密文件后无法用OpenSSL命令行解密

我用EVP_Cipher API实现了AES-256-CBC加密文件的C++代码,代码自身可以正常解密,但用OpenSSL命令行解密加密后的文件时,一直提示“Bad decrypt”错误。

使用的OpenSSL命令:

openssl enc -aes-256-cbc -d -K ae0479555eca5b5228a0ee00ecef15aab729f47ee881cf8b1d3ff18561a47290 -iv 3fa6d97f4807e145b37451fc344e58ca -in test.enc -out test.out -nosalt

我的C++代码如下:

using namespace std;

void encDecFile(const char * input_filepath, bool encrypt) {
  const unsigned char * key = (const unsigned char * )
  "ae0479555eca5b5228a0ee00ecef15aab729f47ee881cf8b1d3ff18561a47290";
  const unsigned char * iv = (const unsigned char * )
  "3fa6d97f4807e145b37451fc344e58ca";

  int intent = encrypt ? 1 : 0;
  std::string output_filepath = input_filepath;

  if (encrypt) {
    const char * ext = ".enc";
    output_filepath = output_filepath + std::string(".enc");
  } else {
    auto pos = output_filepath.find_last_of(".");
    output_filepath = output_filepath.substr(0, pos) + std::string(".out");
  }

  ifstream input_file(input_filepath, std::ios::binary);
  ofstream output_file(output_filepath.c_str(), std::ios::binary);
  int out_len = 0;

  printf("encDecFile - Entry \n");

  if (!(input_file.is_open() && output_file.is_open())) {
    const char * whichFile = input_file.is_open() ? output_filepath.c_str() : input_filepath;
    printf("encDecFile Failed to open %s \n", whichFile);
    return;
  }

  input_file.seekg(0, std::ios::end);
  long long file_size = input_file.tellg();
  input_file.seekg(0, std::ios::beg);
  printf("encDecFile - Input file %s is of Size %lld is opened! \n", input_filepath, file_size);


  EVP_CIPHER_CTX * ctx;
  ctx = EVP_CIPHER_CTX_new();

  EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv, 1);
  EVP_CIPHER_CTX_set_padding(ctx, 1);
  unsigned int blocksize = EVP_CIPHER_block_size(EVP_aes_256_cbc());

  char * in_buf = new char[2048];
  char * out_buf = new char[2048 + blocksize];

  int count = 0;
  while (!input_file.eof()) {
    input_file.read(in_buf, (1 << 20));
    std::streamsize dataSize = input_file.gcount();
    printf("encDecFile - Reading %d chunk of data of size %d \n", ++count, (int) dataSize);
    if (1 == EVP_CipherUpdate(ctx, (unsigned char * ) out_buf, & out_len, (const unsigned char * ) in_buf, (int) dataSize)) {
      output_file.write(out_buf, out_len);
      printf("encDecFile - Written %d bytes of encrypted data \n", out_len);
    } else {
      printf("Encryption failed after for %d Chunk! \n", count);
      break;
    }
  }
  if (1 == EVP_CipherFinal_ex(ctx, (unsigned char * ) out_buf, & out_len)) {
    output_file.write(out_buf, out_len);
    printf("encDecFile - Written %d bytes of final encrypted data \n", out_len);
  } else {
    printf("Encryption failed after to update Final \n");
  }

  input_file.close();
  output_file.close();

  delete[] out_buf;
  EVP_CIPHER_CTX_cleanup(ctx);
  EVP_CIPHER_CTX_free(ctx);

  printf("encDecFile - Done!! \n");

  return;
}

核心问题分析

问题出在密钥和IV的格式处理上:

  • 代码中直接把十六进制字符串当作字节数组传递给EVP_CipherInit_ex,但OpenSSL命令行的-K和-iv参数要求的是十六进制对应的原始字节值。
  • 比如你写的"ae0479555eca5b5228a0ee00ecef15aab729f47ee881cf8b1d3ff18561a47290"是64个字符的十六进制字符串,对应32字节的AES-256密钥,但代码中传递的是这个字符串的ASCII字节(每个字符占1字节),相当于用了64字节的错误密钥,而非32字节的正确密钥。
  • IV同理,你传递的是32字符的ASCII字符串(32字节),但AES-CBC的IV需要16字节(对应32个十六进制字符的解码值)。

解决步骤

  1. 编写十六进制字符串转字节数组的函数:将密钥和IV的十六进制字符串解码成原始字节数组,比如把"ae"转换成0xAE字节。
    示例转换函数:
    bool hexToBytes(const std::string& hexStr, std::vector<unsigned char>& bytes) {
        if (hexStr.length() % 2 != 0) return false;
        bytes.reserve(hexStr.length() / 2);
        for (size_t i = 0; i < hexStr.length(); i += 2) {
            std::string byteStr = hexStr.substr(i, 2);
            char byte = (char)strtol(byteStr.c_str(), nullptr, 16);
            bytes.push_back(byte);
        }
        return true;
    }
    
  2. 修改代码中的密钥和IV初始化:
    std::string keyHex = "ae0479555eca5b5228a0ee00ecef15aab729f47ee881cf8b1d3ff18561a47290";
    std::string ivHex = "3fa6d97f4807e145b37451fc344e58ca";
    std::vector<unsigned char> keyBytes, ivBytes;
    if (!hexToBytes(keyHex, keyBytes) || !hexToBytes(ivHex, ivBytes)) {
        printf("Invalid hex key or IV\n");
        return;
    }
    
  3. 传递正确的字节数组给EVP API:
    EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, keyBytes.data(), ivBytes.data(), 1);
    
  4. 额外检查点:代码中已设置EVP_CIPHER_CTX_set_padding(ctx, 1),对应OpenSSL默认的PKCS#7填充,无需修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 03:17:07