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

C++实现AES-CBC 256加密与SHA-512哈希的异常输出问题及遗留疑问

解答你的AES加密结果异常与遗留疑问

首先恭喜你已经解决了SHA-512跨语言不一致的问题——大小写差异确实是这类问题的常见坑,统一格式化就能轻松对齐。针对你遗留的AES加密结果混杂明文的疑问,我们来拆解代码里的几个关键问题:

问题根源分析

你看到加密结果里同时出现明文和加密数据,主要是由以下几个代码错误导致的:

  1. 输入数据的错误处理
    你把明文"Hello World"直接传入fromHex处理,但fromHex是用来把十六进制字符串转成二进制的,明文本身不是十六进制,这会导致解析出乱码数据。更糟的是,fromHex返回std::string(dest)时,二进制数据里可能包含\0字符,std::string的构造函数遇到\0就会截断,导致数据不完整,同时还存在new char[_size]未释放的内存泄漏。

  2. 加密结果的缓冲区溢出
    加密分支里你定义了char res[inputLength];,但AES-CBC加密后的长度是块对齐的,正确长度应该是((inputLength + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE。用inputLength大小的数组存加密结果,会导致缓冲区溢出,破坏栈上的其他数据(比如之前存储的明文变量),这就是你看到明文混杂在加密结果里的核心原因。

  3. strlen的误用
    加密后的二进制数据大概率包含\0字符,用strlen(res)获取长度会提前截断,导致后续输出时把栈上的其他数据(比如明文)也一并包含进去,进一步加剧了混乱。

  4. strcpy的潜在问题
    之前用strcpy复制二进制数据(密钥、IV、输入),strcpy遇到\0就停止,会导致二进制数据复制不完整。换成memcpy是正确的选择,因为它会按指定长度完整复制。

修正后的关键代码示例

这里给你调整后的核心代码片段,解决上述问题:

修正AES-CBC 256函数

#include <vector>
#include <openssl/aes.h>

std::string Encryption::AES::cbc256(const unsigned char* data, size_t len, const unsigned char* key, const unsigned char* iv, bool encrypt) {
    AES_KEY aes_key;
    if (encrypt) {
        if (AES_set_encrypt_key(key, 256, &aes_key) != 0) {
            // 处理密钥错误
            return "";
        }
    } else {
        if (AES_set_decrypt_key(key, 256, &aes_key) != 0) {
            // 处理密钥错误
            return "";
        }
    }

    // 计算正确的输出长度:加密时块对齐,解密时输入应已对齐
    size_t output_len = encrypt ? ((len + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE : len;
    std::vector<unsigned char> res(output_len);
    
    // 复制IV(因为AES_cbc_encrypt会修改IV)
    unsigned char iv_copy[AES_BLOCK_SIZE];
    memcpy(iv_copy, iv, AES_BLOCK_SIZE);

    AES_cbc_encrypt(data, res.data(), len, &aes_key, iv_copy, encrypt ? AES_ENCRYPT : AES_DECRYPT);

    if (encrypt) {
        // 加密后转十六进制输出
        return Encryption::Utils::toHex(res.data(), output_len);
    } else {
        // 解密后去掉PKCS#7填充(如果加密时用了填充)
        if (!res.empty()) {
            size_t padding_len = res.back();
            if (padding_len > 0 && padding_len <= AES_BLOCK_SIZE) {
                res.resize(res.size() - padding_len);
            }
        }
        return std::string(res.begin(), res.end());
    }
}

修正fromHex工具函数

#include <string>
#include <sstream>
#include <stdexcept>

std::string Encryption::Utils::fromHex(const std::string& hex_str) {
    if (hex_str.size() % 2 != 0) {
        throw std::invalid_argument("Hex string length must be even");
    }

    std::string result;
    result.reserve(hex_str.size() / 2);
    
    for (size_t i = 0; i < hex_str.size(); i += 2) {
        std::string byte_str = hex_str.substr(i, 2);
        char byte = static_cast<char>(std::stoul(byte_str, nullptr, 16));
        result.push_back(byte);
    }
    return result;
}

额外提示

  • 加密时记得添加PKCS#7填充(AES要求输入长度是块的倍数),修正后的加密函数已经处理了块对齐,解密时也对应去掉了填充。
  • 避免用栈数组存储动态长度的数据,改用std::vector更安全,防止缓冲区溢出。
  • 处理二进制数据时,始终用unsigned char类型,避免符号扩展导致的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 21:07:29