1

I want to move from mcrypt_encrypt() to openssl_encrypt() for AES 256 encryption

But the encrypted data are different !

For example mcrypt_encrypt() output:

Od2i8FHmWvMeXt+HwCy7k93koPVClK1erHsZwoB6sUE=

and openssl_encrypt() output:

Od2i8FHmWvMeXt+HwCy7kyCt0nvHTaO4IdjdiF15LAc= 

My code:

<?php
$encryption_key = openssl_random_pseudo_bytes(32);
$iv = openssl_random_pseudo_bytes(16);
$data = "Here's some data to encrypt!";
$encrypted = openssl_encrypt($data, "aes-256-cbc", $encryption_key, 0, $iv);
echo "encrypted: $encrypted\n\n";
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $encryption_key, $data, MCRYPT_MODE_CBC, $iv));
echo "encrypted: $encrypted\n\n";
?>

What is the problem? Thank you

Sos.
  • 914
  • 10
  • 14
  • 1
    Notice how the ends are only different? ... This may help: https://stackoverflow.com/questions/41181905/php-mcrypt-encrypt-to-openssl-encrypt-and-openssl-zero-padding-problems – IncredibleHat Mar 09 '18 at 21:09
  • @IncredibleHat This solves my problem! Thank you very much – Sos. Mar 09 '18 at 21:14
  • =) Sorry I was being obtuse earlier... – IncredibleHat Mar 09 '18 at 21:15
  • @IncredibleHat No problem.. Thank you ! – Sos. Mar 09 '18 at 21:15
  • It is best not to use PHP mcrypt, it is abandonware, has not been updated in years and **does not support standard PKCS#7 (née PKCS#5) padding, only non-standard null padding** that can't even be used with binary data. mcrypt has many outstanding [bugs](https://sourceforge.net/p/mcrypt/bugs/) dating back to 2003. The mcrypt-extension is deprecated will be removed in PHP 7.2. Instead consider using [defuse](https://github.com/defuse/php-encryption) or [RNCryptor](https://github.com/RNCryptor), they provide a complete solution and are being maintained and is correct. – zaph Mar 09 '18 at 21:25
  • Sadly the encryption key is not on the question. – zaph Mar 09 '18 at 21:30

1 Answers1

3

It is most likely the padding. Notice that the first block is the same for each and the last block is different.

The text being encrypted is 28 bytes so the the last block will have 4 bytes of padding: 16-(28%16) = 4.

PHP mcrypt does not support standard PKCS#7 (née PKCS#5) padding, only non-standard null padding.

So PHP mcrypt will appoint 4-bytes of 0x00 and openssl 4-bytes of 0x04. See PKCS#7 padding.

So if you want to create the same encrypted output with openssl_encrypt you need too specify zero padding option (OPENSSL_ZERO_PADDING) and add the null padding yourself. Note: null padding is not robust because it can not correctly handle all binary data.

Example: openssl_encrypt($data, "aes-256-cbc", $encryption_key, OPENSSL_ZERO_PADDING, $iv);


mcrypt_encrypt():
Base64: Od2i8FHmWvMeXt+HwCy7k93koPVClK1erHsZwoB6sUE=
Hex: 39DDA2F051E65AF31E5EDF87C02CBB93 DDE4A0F54294AD5EAC7B19C2807AB141

openssl_encrypt:
Base64: Od2i8FHmWvMeXt+HwCy7kyCt0nvHTaO4IdjdiF15LAc=
Hex: 39DDA2F051E65AF31E5EDF87C02CBB93 20ADD27BC74DA3B821D8DD885D792C07

zaph
  • 111,848
  • 21
  • 189
  • 228
  • when using OPENSSL_ZERO_PADDING the output is empty – Sos. Mar 09 '18 at 21:45
  • I got that from [openssl_encrypt](https://secure.php.net/manual/en/function.openssl-encrypt.php), perhaps you are using a different version. From the doc comments: *So, OPENSSL_ZERO_PADDING disables padding for the context, which means that you will have to manually apply your own padding out to the block size. Without using OPENSSL_ZERO_PADDING, you will automatically get PKCS#7 padding.* – zaph Mar 09 '18 at 21:48
  • `OPENSSL_ZERO_PADDING` sorted out my issue of the openssl result being too long but matching first blocks +1 – RSM Aug 27 '19 at 20:50
  • 1
    Just a note. I had to mimic the 3DES ECB mcrypt, and the padding has one more difference. When the plaintext length fits to the block size boundary, there is actually no padding at all, but in PKCS#7, there is one more block with padding. So, with plaintext `hello wo`, the mcrypt padded data will be `hello wo`, but in the PKCS#7 it will be `hello wo\x08\x08\x08\x08\x08\x08\x08\x08`. – Richard Toth Jan 23 '20 at 15:30