2

Actually I'm using Mcrypt but I'm moving to OpenSSL and I need to be able to use it the exact same way as Mcrypt.

This is how I'm encrypting

mcrypt_encrypt(MCRYPT_DES, $key, $text, MCRYPT_MODE_cbc, "\0\0\0\0\0\0\0\0");

For the decryption, I already managed to do it in OpenSSL, both are working the same exact ways

//Using Mcrypt
mcrypt_decrypt(MCRYPT_DES, $key, $enc, MCRYPT_MODE_cbc, "\0\0\0\0\0\0\0\0");

//Using Openssl
openssl_decrypt($enc, 'des-cbc', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); 

For the encryption using OpenSSL, this is my test code

$key = "123456SO";
$text = "name=louis&cp=75013";

$encMcrypt = mcrypt_encrypt(MCRYPT_DES, $key, $text, MCRYPT_MODE_cbc, "\0\0\0\0\0\0\0\0");
$encOpenssl = openssl_encrypt($text, "des-cbc", $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, "\0\0\0\0\0\0\0\0");

echo "Mcrypt : " . urlencode(base64_encode($encMcrypt));
echo " OpenSsl : " . urlencode(base64_encode($encOpenssl));

And this is the output :

Mcrypt : f0tF0ERITdKiI2SxrttYAJBVNBtoGR%2BD OpenSsl :

This is the official list of methods, but I can't find the DES methods.

I know that OpenSSL declared DES weak, but I still need to use it in my situation.

How can I encrypt in DES-CBC using OpenSSL and make it behave the same way as the Mcrypt function?

Edit:

If I removed the OPENSSL_ZERO_PADDING option, the result is almost the one expected

Code:

openssl_encrypt($text, "des-cbc", $key, OPENSSL_RAW_DATA , "\0\0\0\0\0\0\0\0");

output:

Mcrypt  : f0tF0ERITdKiI2SxrttYAJBVNBtoGR%2BD
OpenSsl : f0tF0ERITdKiI2SxrttYANpJ%2BZaEiIFr

The first part of the string is correct but at the end it differs from the output of the Mcrypt encryption string.

AJM
  • 1,317
  • 2
  • 15
  • 30
CE_
  • 1,078
  • 2
  • 16
  • 33
  • 3
    _mcyrpt_ uses Zero padding, _openssl_ PKCS7 padding. For _openssl_, Zero padding must be implemented explicitly. First PKCS7 padding must be disabled with `OPENSSL_ZERO_PADDING` (note, the name is badly chosen: this flag only disables PKCS7 padding, it does not enable Zero padding). Next, implement Zero Padding, i.e. pad the plaintext with `0x00` values if its length is not already an integer multiple of the blocksize (8 bytes for DES), i.e. for the posted plaintext: `"name=louis&cp=75013\0\0\0\0\0"` which gives the _mcrypt_ ciphertext. – Topaco Aug 14 '20 at 11:14
  • 3
    Concerning the decryption, it should be added that _mcrypt_ does not _explicitly_ remove the Zero padding. Therefore, it's functionally identical to set merely `OPENSSL_ZERO_PADDING` in the decryption with _openssl_. – Topaco Aug 14 '20 at 11:17
  • @Topaco I didn't knew that ’OPENSSL_ZERO_PADDING’ actually did not enable Zero padding in the encryption, thanks. I will try to implement the zero padding by myself – CE_ Aug 14 '20 at 11:21

1 Answers1

1

Thanks to @Topaco I managed to make it work

I added the OPENSSL_ZERO_PADDING option to disable the PKCS7 padding, then I created a function to manually pad my string with 0x00

function zero_padding($text)
{
    if (strlen($text) % 8)
        $text = str_pad($text,strlen($text) + 8 - strlen($text) % 8, "\0");
    
    return $text;
}

$key = "123456SO";
$text = "name=louis&cp=75013";

$encMcrypt = mcrypt_encrypt(MCRYPT_DES, $key, $text, MCRYPT_MODE_cbc, "\0\0\0\0\0\0\0\0");
$encOpenssl = openssl_encrypt(zero_padding($text), "des-cbc", $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, "\0\0\0\0\0\0\0\0");

$encMcrypt = urlencode(base64_encode($encMcrypt));
$encOpenssl = urlencode(base64_encode($encOpenssl));

echo "Mcrypt :" . $encMcrypt;
echo "OpenSsl:" . $encOpenssl;

Output:

Mcrypt : f0tF0ERITdKiI2SxrttYAJBVNBtoGR%2BD
OpenSsl: f0tF0ERITdKiI2SxrttYAJBVNBtoGR%2BD
CE_
  • 1,078
  • 2
  • 16
  • 33