PHP中的OpenSSL和Mcrypt之间的输出不同 - 为什么?

时间:2013-11-22 10:17:57

标签: php encryption openssl mcrypt

我目前正在开发一个大型应用程序,其中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=

我们怀疑填充问题,但我们现在无法找到解决方案。

任何暗示都赞赏!

1 个答案:

答案 0 :(得分:1)

经过一番研究,似乎MCrypt用零字节填充输入,而OpenSSL使用PKCS#7填充,这解释了不相同的输出。我们设法通过删除PHP端的手动填充,并在Windows端实现PKCS#7填充来获得相同的结果。