使用 OpenSSL/C++ 和 PHP/Mcrypt 的 AES-128-CBC 加密:仅解密第一个块
Posted
技术标签:
【中文标题】使用 OpenSSL/C++ 和 PHP/Mcrypt 的 AES-128-CBC 加密:仅解密第一个块【英文标题】:AES-128-CBC encryption with OpenSSL/C++ and PHP/Mcrypt: the 1st block is decrypted only 【发布时间】:2013-12-07 10:45:29 【问题描述】:我编写的程序必须与基于 php 的 Web 服务交换加密数据。我使用 C++ 和 OpenSSL 在 CBC 模式下使用 AES-128 加密数据。我将 base64 编码的数据(IV 和密文)发送到 HTTP 服务器,PHP 必须使用 Mcrypt 解密数据。但是,只有第一个块解密成功,其他块变成垃圾。 我完全不明白:我们如何才能仅在 CBC 模式下解密第一个块?如果 IV、密钥或算法设置(如密钥大小/块大小/轮数)错误,我们将无法接收正确解密的第一个块;如果解密参数没问题,其他区块怎么可能不解密呢? 当我解密 PHP 无法使用 OpenSSL/C++ 解密的相同密文时,解密成功。 PHP 也是如此:我可以在 CBC 模式下加密和解密数据。但出于任何原因,OpenSSL EVP_aes_128_cbc 和 mcrypt 'rijndael-128' 不兼容。 我的解密代码如下:
$chipher = mcrypt_module_open('rijndael-128', '', 'cbc', '');
mcrypt_generic_init($chipher, $key, $iv);
$decrypted_data = mdecrypt_generic($chipher, $encrypted_data);
是 mcrypt 的错误还是有什么方法可以使用 OpenSSL AES-128-CBC 加密数据并使用 PHP mcrypt 解密?
【问题讨论】:
您是否有理由不能使用像 TLS 这样专为此类用例设计的标准协议? 我正在考虑一些破解保护;在 Windows 上添加受信任的根 CA 并使用 Fiddler 之类的工具拦截 HTTPS 流量通常很简单;这就是为什么我决定使用自定义加密而不是 SSL,所以 atacker 将不得不反汇编和修改我的代码来破解系统,而不仅仅是像 Fiddler 这样的标准工具使用。 但是一旦主密钥被“破解”,那么整个系统的所有用户都会受到威胁。您需要确定您是在寻找安全性还是混淆性。 当您将程序提供给可能试图破解它的用户时,混淆是唯一的选择;但是,我认为非标准打包+自定义加密的逆向工程比标准HTTPS协议使用更复杂;在我看来,反汇编通常比额外安装 CA 来绕过 HTTPS 加密更复杂。当然,任何软件仍然可以破解,但我想让这项工作更复杂。 hm ...在这种情况下我能想到的唯一原因是:块 0(iv) 和块 1 传输正常,但随后一些其他内容被插入到数据流中,比如块之间的分隔字符...您能否确认加密的输出具有正确的大小,例如 iv + x * blocksize 的大小? --- 你能确认你没有混淆操作模式吗?一方面是CBC,另一方面是PCBC 【参考方案1】:嗯,错误出在 C++ 方面。我加密的数据是分部分来的,所以我不得不多次调用 EVP_CipherUpdate;因为在重复调用 EVP_CipherUpdate 时,复制到输出缓冲区的数据太多,而且只有最后一个块,所以我不得不重复调用 EVP_CipherInit_ex 来清理 OpenSSL 上下文中的内部缓冲区。当我调用 EVP_CipherInit_ex 时,它会重置 IV,所以在某个时间点之后解密变得不可能。 解决方案是在每次 EVP_CipherUpdate 调用后将 IV 的最后一个版本(context.iv 指向最后一个 IV,context.oiv 指向原始版本)保存在缓冲区中,并将其传递给 EVP_CipherInit_ex 以允许 OpenSSL 分部分加密数据。当我这样做时,mcrypt 能够解密整个数据甚至删除填充。 所以,mcrypt 非常好,我看到的问题是我的程序错误,而不是 mcrypt。
【讨论】:
以上是关于使用 OpenSSL/C++ 和 PHP/Mcrypt 的 AES-128-CBC 加密:仅解密第一个块的主要内容,如果未能解决你的问题,请参考以下文章
验证openssl c ++中的签名,该签名由JAVA DSA签名?
AES (aes-cbc-128, aes-cbc-192, aes-cbc-256) 使用 openssl C 加密/解密