mcrypt_encrypt to openssl_encrypt, and OPENSSL_ZERO_PADDING problems
mcrypt_encrypt zero-pads input data if it's not a multiple of the blocksize. This leads to ambiguous results if the data itself has trailing zeroes. Apparently OpenSSL doesn't allow you to use zero padding in this case, which explains the false return value.
You can circumvent this by adding the padding manually.
$message = "Lorem ipsum";
$key = "123456789012345678901234";
$iv = "12345678";
$message_padded = $message;
if (strlen($message_padded) % 8) {
$message_padded = str_pad($message_padded,
strlen($message_padded) + 8 - strlen($message_padded) % 8, "\0");
}
$encrypted_mcrypt = mcrypt_encrypt(MCRYPT_3DES, $key,
$message, MCRYPT_MODE_CBC, $iv);
$encrypted_openssl = openssl_encrypt($message_padded, "DES-EDE3-CBC",
$key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv);
printf("%s => %s\n", bin2hex($message), bin2hex($encrypted_mcrypt));
printf("%s => %s\n", bin2hex($message_padded), bin2hex($encrypted_openssl));
This prints both as equal.
4c6f72656d20697073756d => c6fed0af15d494e485af3597ad628cec
4c6f72656d20697073756d0000000000 => c6fed0af15d494e485af3597ad628cec
Comments
-
yivi almost 2 years
I have this
mcrypt_encrypt
call, for a given$key
,$message
and$iv
:$string = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv);
I'd like to change the
mcrypt_encrypt
call to anopenssl_encrypt
one, to future-proof this.By having
$mode = 'des-ede3-cbc'
or$mode = '3DES';
and$options = true
I get the more similar response, but not identical. Is there other way to call it to get a perfect match?I am getting this (base64_encoded) for a lorem-ipsum
$message
+$key
combinations, so I am starting to believe one function or the other are padding somewhat the message before encrypting...for mcrypt:
"Y+JgMBdfI7ZYY3M9lJXCtb5Vgu+rWvLBfjug2GLX7uo="
for for openssl:
"Y+JgMBdfI7ZYY3M9lJXCtb5Vgu+rWvLBvte4swdttHY="
Tried using
$options
to pass OPENSSL_ZERO_PADDING, but passing anything but 1 (OPENSSL_RAW_DATA, or true) results in an empty string ...Neither using
OPENSSL_ZERO_PADDING
norOPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
work... :( I'm using "OpenSSL 1.0.2g 1 Mar 2016".Already read this q&a, but it does not help me. Not the only one with padding troubles, but no solution in sight so far. Second answer talks about adding padding to mcrypt call, I would really want to remove padding from openssl encryption call...
-
Nickolay Olshevsky over 7 yearsWhy should I spend time on that?
-
yivi over 7 years
OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING
do not work. Probably a bug in phps openssl implementation or something? Removing the extra characters from the unencrypted data doesn't work for me. This string is used as a verification signature: I'm provided with one and a some data, create this encrypted data to match the received signature. I don't control the system on the other side. Modifying mcrypt_ call so it matches openssl_ doesn't help me, I need openssl_ to match mcrypt_ :) -
Nickolay Olshevsky over 7 yearsYou can add zero padding by yourself, then call openssl_encrypt. This will add openssl's padding as well. Then remove that padding (last 8 bytes). Then output should match mcrypt_encrypt
-
yivi over 7 yearsI'm not sure I'm following. Can you post this as part of your answer, with a code example showing what you mean? Thanks.