Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encrypt by mcrypt and decrypt by openssl with mode CBC and cipher BLOWFISH

We have encrypted some data in mcrypt cipher BLOWFISH and mode is CBC String encrypted in php5.5 and need to decrypt this in php7.1 (php version upgraded)

Following is our code to trying to decrypt mcrypt string using openssl

$data = "Lorem ipsum";
$key = "12345678";
$iv = "12345678";

$encrypted = mcrypt_encrypt(
    MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_CBC, $iv);
echo $encrypted . PHP_EOL;

$decrypted = openssl_decrypt(
    $encrypted, "BF-CBC", $key,
    OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);

echo $decrypted;

Above code is not decrypting string. Please suggest me any method to decrypt string

like image 522
Manmohan Avatar asked Sep 18 '18 13:09

Manmohan


1 Answers

You were missing one option on the openssl side: OPENSSL_DONT_ZERO_PAD_KEY.

If the length of the key given to openssl_decrypt() is shorter than the default key length for the cipher (Blowfish in this case) the PHP openssl glue code expands the key to that length by adding additional zeros. You can see it happen here. The mcrypt implementation does not do that key padding. The openssl default key length for Blowfish is 16 bytes, so if your key is shorter than 16 bytes, the keys for mcrypt and openssl will be different -- unless you use the openssl option to not do that padding of the key.

Verifying that this is indeed the case:

# bf.php
$data = "Lorem ipsum";
$key = "12345678";
$iv = "12345678";

$encrypted = mcrypt_encrypt(
    MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_CBC, $iv);
#echo $encrypted . PHP_EOL;

$decrypted = openssl_decrypt(
    $encrypted, "BF-CBC", $key,
    OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING | OPENSSL_DONT_ZERO_PAD_KEY, $iv);

echo $decrypted . PHP_EOL;

and

$ php bf.php
Lorem ipsum

This comment by t.m.adam is relevant too, with regard to the zeroes at the end. Expanding on that suggestion:

var_dump($decrypted);
var_dump(rtrim($decrypted));

gives

string(16) "Lorem ipsum"
string(11) "Lorem ipsum"

You can not do rtrim for binary data of course, in that case you will have to remember or store what the size of your original plaintext was, or manually pad the data according to some useful padding schema as opposed to zero-padding. mcrypt_encrypt() does not seem capable of doing that.

like image 52
Reinier Torenbeek Avatar answered Oct 14 '22 23:10

Reinier Torenbeek