我目前正在开发一个大型应用程序,其中Windows软件需要解密PHP脚本生成的字节流。在花了很多时间调整Windows应用程序和PHP脚本之后,我们终于设法解密了一个使用Blowfish算法加密的简单字符串。
在我们的测试中,我们使用了Mcrypt和OpenSSL,但只有MCrypt提供了正确的输出(至少是Windows客户端理解的输出)。
我们目前正在尝试理解为什么两个库的行为不同,以确保我们做正确的事情。此外,正如我们所读到的,现在强烈推荐使用OpenSSL并提供比MCrypt更多的功能,我们现在更喜欢使用OpenSSL。
为了找出错误,我们使用MCrypt和OpenSSL进行了一项非常简单的测试,该测试使用相同的输入但产生不同的输出。请注意,我们仅使用null IV进行测试,我们知道这不是一件安全的事情。我们在CBC模式下使用Blowfish,使用256位二进制密钥。
MCrypt代码:
$key = hash ("sha256", "toto", true);
$alg = MCRYPT_BLOWFISH;
$mode = MCRYPT_MODE_CBC;
$data = "tata";
$encrypted = mcrypt_encrypt($alg, $key, $data, $mode, "\0\0\0\0\0\0\0\0");
$encrypted = base64_encode($encrypted);
输出(Windows客户端正确理解):
kc7bO7jTWF8=
OpenSSL代码:
$key = hash ("sha256", "toto", true);
$method = "BF-CBC";
$data = "tata\0\0\0\0"; //Completely different results if we don’t pad the input ourself
$encrypted = openssl_encrypt($data, $method, $key, true, "\0\0\0\0\0\0\0\0");
$encrypted = base64_encode($encrypted);
输出:
kc7bO7jTWF/+NdPlZPBxMw==
如您所见,两个输出以相同的值开头,但OpenSSL输出略大(16个字节)。为什么?如果我们不手动填充输入,我们得到一个看起来有效但不同于MCrypt的不同输出:
输出:
iCug+W0s2lc=
我们怀疑填充问题,但我们现在无法找到解决方案。
任何暗示都赞赏!
答案 0 :(得分:1)
经过一番研究,似乎MCrypt用零字节填充输入,而OpenSSL使用PKCS#7填充,这解释了不相同的输出。我们设法通过删除PHP端的手动填充,并在Windows端实现PKCS#7填充来获得相同的结果。