密码学 - 发布模式下的异常行为

Cryptography - Bizzare behaviour in Release mode

我有一个项目使用 Crypto++

Crypto++ 是一个构建在静态库中的自己的项目。
除此之外,我还有另一个大型项目使用一些 Crypto++ 类 并处理各种算法,它也构建在静态库中。

其中两个函数是:

long long MyClass::EncryptMemory(std::vector<byte> &inOut, char *cPadding, int rounds)
{
    typedef std::numeric_limits<char> CharNumLimit;
    char sPadding = 0;
    //Calculates padding and returns value as provided type
    sPadding = CalcPad<decltype(sPadding)>(reinterpret_cast<MyClassBase*>(m_P)->BLOCKSIZE, static_cast<int>(inOut.size()));
    //Push random chars as padding, we never care about padding's content so it doesn't matter what the padding is
    for (auto i = 0; i < sPadding; ++i)
        inOut.push_back(sRandom(CharNumLimit::min(), CharNumLimit::max()));
    std::size_t nSize = inOut.size();
    EncryptAdvanced(inOut.data(), nSize, rounds);
    if (cPadding)
        *cPadding = sPadding;
    return nSize;
}

//Removing the padding is the responsibility of the caller.
//Nevertheless the string is encrypted with padding
//and should here be the right string with a little padding
long long MyClass::DecryptMemory(std::vector<byte> &inOut, int rounds)
{
    DecryptAdvanced(inOut.data(), inOut.size(), rounds);
    return inOut.size();
}

其中 EncryptAdvancedDecryptAdvanced 将参数传递给 Crypto++ 对象。

//...
AdvancedProcessBlocks(bytePtr, nullptr, bytePtr, length, 0);
//...

到目前为止,这些功能运行完美,数月以来未对它们应用任何修改。 尽管传递给它们的调用和数据没有改变,但围绕它们的逻辑已经发生了变化。

正在加密/解密的数据比较小,但具有动态大小,正在填充if (datasize % BLOCKSIZE)有余数。
示例:AES 块大小为 16。数据为 31。填充为 1。数据现在为 32。

加密后解密前的字符串是一样的-如图。

运行 所有这些在 调试模式 中显然都按预期工作。即使 运行 在另一台计算机上运行此程序(为 DLL 安装了 VS),它也没有任何区别。数据加密解密正确

尝试 运行 在 发布模式 中的相同代码会导致完全不同的加密字符串,而且它无法正确解密 - "trash data" 已解密.错误加密或解密的数据是一致的——总是解密相同的垃圾。 key/password 和 rounds/iterations 始终相同

附加信息:数据保存在文件中 (ios_base::binary) 并在调试模式下正确处理,来自同一解决方案中使用相同静态库的两个不同程序 (y/ies)。

这个调试/发布问题的原因可能是什么?

我重新检查了几次 git 历史记录,通过代码调试了好几天,但我找不到任何可能导致此问题的原因。 如果需要任何信息 - 除了(这里是不可能的)MCVE,请发表评论。

显然这是 CryptoPP 中的错误。 Rijndael / AES 的最小密钥长度设置为 8 而不是 16。使用 8 字节的无效密钥长度将导致越界访问 Rcon 值的就地数组。这个 8 字节的密钥长度目前被报告为有效,必须在 CryptoPP 中修复。

有关详细信息,请参阅 this issue on github。 (正在进行的对话)