php: mcrypt_encrypt to openssl_encrypt, and OPENSSL_ZERO_PADDING problems

本小妞迷上赌 提交于 2019-11-26 12:46:58

问题


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 an openssl_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\'m getting this (base64_encoded) for a lorem-ipsum $message+$key combinations, so I\'m 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 nor OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING work... :( I\'m using \"OpenSSL 1.0.2g 1 Mar 2016\".

Already read this q&a, but it doesn\'t 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...


回答1:


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



回答2:


mcrypt_encrypt uses zeroes to pad message to the block size. So you can add zeroes to the tail of your raw data, and then encrypt the block.

Using OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING should work. If it doesn't, then you can remove padding from the decrypted data by yourself.



来源:https://stackoverflow.com/questions/41181905/php-mcrypt-encrypt-to-openssl-encrypt-and-openssl-zero-padding-problems

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!