Разница в том, что mcrypt_encrypt
/ mcrypt_decrypt
использует заполнение нулями и openssl_encrypt
/ openssl_decrypt
использует PKCS7-Padding . Это можно легко проверить, применив Zero-Padding для openssl
: для этого PKCS7-Padding должен быть отключен с флагом OPENSSL_ZERO_PADDING
( важно : несмотря на название, этот флаг не означает, чтоЗаполнение нулями используется, но заполнение вообще не применяется), и открытый текст должен дополняться значениями 0
до следующего целого числа, кратного размеру блока (8
байтов для Triple-DES), если длина уже не указанасоответствует целому кратному размеру блока:
<?php
function zeroPadding($data, $size) {
$oversize = strlen($data) % $size;
return $oversize == 0 ? $data : ($data . str_repeat("\0", $size - $oversize));
}
// Something is wronguration.
$data = 'FOO';
$secret = '111222333444555666777888';
$iv = 'ABCDEFGH';
// Encrytp & decrypt with mcrypt.
$encMcrypt = bin2hex(mcrypt_encrypt(MCRYPT_3DES, $secret, utf8_encode($data), MCRYPT_MODE_CBC, $iv));
$decMcrypt = mcrypt_decrypt(MCRYPT_3DES, $secret, hex2bin($encMcrypt), MCRYPT_MODE_CBC, $iv);
// Encrytp & decrypt with openssl.
$encOpenSSLZeroPadding = bin2hex(openssl_encrypt(utf8_encode(zeroPadding($data, 8)), 'DES-EDE3-CBC', $secret, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
$decOpenSSLZeroPadding = openssl_decrypt(hex2bin($encOpenSSLZeroPadding), 'DES-EDE3-CBC', $secret, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
// Result.
echo "data padded: " . bin2hex(zeroPadding($data, 8)) . "<br>";
echo "mcrypt encrypt: $encMcrypt <br>";
echo "openssl encrypt: $encOpenSSLZeroPadding <br>";
echo "mcrypt decrypt: $decMcrypt <br>";
echo "mcrypt decrypt: " . bin2hex($decMcrypt) . "<br>";
echo "openssl decrypt: $decOpenSSLZeroPadding" . "<br>";
echo "openssl decrypt: " . bin2hex($decOpenSSLZeroPadding);
со следующим выводом:
data padded: 464f4f0000000000
mcrypt encrypt: 3f9bd8d5f844ff67
openssl encrypt: 3f9bd8d5f844ff67
mcrypt decrypt: FOO
mcrypt decrypt: 464f4f0000000000
openssl decrypt: FOO
openssl decrypt: 464f4f0000000000
Вместо использования заполнения нулями в openssl
-контексте, PKCS7-Обивка может быть использована в mcrypt
-контексте. Независимо от того, какой из двух вариантов используется, с одинаковыми отступами mcrypt
и openssl
результаты идентичны!
Следует отметить (см. Шестнадцатеричный вывод), что mcrypt
не удаляет ноль-Паддинг во время дешифрования (в отличие от openssl
, который удаляет PKCS7-Padding во время дешифрования). Кроме того, Zero-Padding ненадежен по сравнению с PKCS7-Padding. Если требования позволяют это (что в вашем случае, вероятно, не так из-за внешнего поставщика), следует использовать PKCS7-Padding.
Кроме того, оба опубликованных варианта используют один и тот же алгоритм, а именно Triple-DES в CBC -режим. Triple-DES имеет размер блока 8
байтов и размер ключа 24
байтов. Triple-DES не идентичен DES , но основан на DES в том смысле, что состоит из трех прогонов DES (encryption-decryption-encryption = ede). mcrypt
указывает Triple-DES / CBC с двумя параметрами, MCRYPT_3DES
(Triple-DES) и MCRYPT_MODE_CBC
(режим CBC), в то время как openssl
использует только один параметр, DES-EDE3-CBC
.
Для Triple-DES существует несколько Keying-Options . 3TDEA
использует три независимых ключа DES и указывается в контексте openssl
с DES-EDE3-CBC
, что предполагает 24
байтовый ключ, 2TDEA
использует два независимых ключа и может быть задано в контексте openssl
альтернативно с DES-EDE-CBC
, который ожидает ключ 16
.
Triple-DES намного медленнее, чем современный AES, но имеет сопоставимую защиту. Как и в случае с отступами, вы должны переключиться на AES, если это возможно.