Вопрос

I’m currently working on a large application in which a Windows software needs to decrypt a stream of bytes generated by a PHP script. After having spent a lot of time tweaking both the Windows application and the PHP script we finally managed to decrypt a simple string encrypted using the Blowfish algorithm.

During our tests, we used both Mcrypt and OpenSSL but only MCrypt gave a correct output (at least, an output understood by the Windows client).

We’re currently trying to understand why the two libraries behave differently in order to be sure we’re doing the right things. Furthermore, as we read that OpenSSL is now highly recommended and offers much more features than MCrypt we would prefer using OpenSSL now.

To locate the mistake we’ve done a very simple test using MCrypt and OpenSSL that uses the same input but produces a different outputs. Please note we’re using a null IV for tests purposes only, we know that’s not a safe thing to do. We’re using Blowfish in CBC mode, with a 256 bit binary key.

MCrypt code :

    $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);

Output (correctly understood by the Windows client) : kc7bO7jTWF8=

OpenSSL code :

   $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);

Output : kc7bO7jTWF/+NdPlZPBxMw==

As you see the two outputs start with the same values, but OpenSSL output is slightly larger (16 bytes). Why ? If we don’t pad manually the input, we got a different output that seems to have a valid size but differs from MCrypt :

Output : iCug+W0s2lc=

We suspect a padding issue but we were unable to find a solution right now.

Any hint appreciated!

Это было полезно?

Решение

After some research, it appears that MCrypt pads the input with zero bytes, while OpenSSL uses PKCS#7 padding, which explains the non-identical output. We managed to get the same results by removing the manual padding on the PHP side, and implementing a PKCS#7 padding on the Windows side.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top