Подтвердить что ты не робот

Php: mcrypt_encrypt to openssl_encrypt и проблемы с OPENSSL_ZERO_PADDING

У меня есть этот вызов mcrypt_encrypt для заданных $key, $message и $iv:

$string = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv);

Я бы хотел изменить вызов mcrypt_encrypt на вызов openssl_encrypt, чтобы это было в будущем.

Имея $mode = 'des-ede3-cbc' или $mode = '3DES'; и $options = true, я получаю более похожий ответ, но не идентичный. Есть ли другой способ назвать это, чтобы получить идеальное совпадение?

Я получаю это (base64_encoded) для комбинаций lorem-ipsum $message + $key, поэтому я начинаю верить, что одна или другая функция несколько дополняют сообщение перед шифрованием...

для Mcrypt

"Y+JgMBdfI7ZYY3M9lJXCtb5Vgu+rWvLBfjug2GLX7uo="

для для openssl

"Y+JgMBdfI7ZYY3M9lJXCtb5Vgu+rWvLBvte4swdttHY="

Попытка использования $ options для передачи OPENSSL_ZERO_PADDING, но передача чего угодно, кроме 1 (OPENSSL_RAW_DATA или true), приводит к пустой строке...

Ни использование OPENSSL_ZERO_PADDING, ни OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING не работают... :( Я использую "OpenSSL 1.0.2g 1 марта 2016".

Уже прочитал этот вопрос, но мне это не помогло. Не только один с проблемами заполнения, но пока не видно решения. (Второй ответ говорит о добавлении заполнения к вызову mcrypt, я бы действительно хотел удалить заполнение из вызова шифрования openssl...

4b9b3361

Ответ 1

mcrypt_encrypt входные данные с нулевой позицией, если это не кратное размеру блока. Это приводит к неоднозначным результатам, если сами данные имеют завершающие нули. По-видимому, OpenSSL не позволяет вам использовать нулевое дополнение в этом случае, что объясняет ложное возвращаемое значение.

Вы можете обойти это, добавив дополнение вручную.

$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));

Отпечатывается как равное.

4c6f72656d20697073756d => c6fed0af15d494e485af3597ad628cec
4c6f72656d20697073756d0000000000 => c6fed0af15d494e485af3597ad628cec

Ответ 2

mcrypt_encrypt использует нули для ввода сообщения в размер блока. Таким образом, вы можете добавить нули в хвост ваших необработанных данных, а затем зашифровать блок.

Использование OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING должно работать. Если это не так, вы можете удалить прописку из дешифрованных данных самостоятельно.