Мне нечего добавить к ответу Мартена , за исключением того, что я подумал, что было бы неплохо показать код, иллюстрирующий его слова.
mcrypt
добавляет нули для заполнениядо открытого текста до кратного размера блока BF, равного 8 байтам, что можно показать, печатая шестнадцатеричные числа как открытого текста, так и зашифрованного зашифрованного текста:
$key = "supersecretkey";
$data = "foobar";
$ctxt = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_ECB);
$ptxt = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $ctxt, MCRYPT_MODE_ECB);
echo bin2hex($data).PHP_EOL;
echo bin2hex($ptxt).PHP_EOL;
дает следующие шестнадцатеричные числа:
666f6f626172
666f6f6261720000
openssl
по умолчанию использует заполнение PKCS # 5, которое в данном случае добавляет 2 байта со значением 2 в конце блока:
$key = "supersecretkey";
$data = "foobar";
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY;
$ctxt = openssl_encrypt($data, 'BF-ECB', $key, $opts);
$ptxt = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $ctxt, MCRYPT_MODE_ECB);
echo bin2hex($data).PHP_EOL;
echo bin2hex($ptxt).PHP_EOL;
дает
666f6f626172
666f6f6261720202
Зашифрованный текст для mcrypt
и openssl
может быть согласован путем добавления байтов заполнения вручную.Обратите внимание на опции OPENSSL_ZERO_PADDING
и добавление "\0\0"
:
$key = "supersecretkey";
$data = "foobar";
$ctxt_mc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_ECB);
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY | OPENSSL_ZERO_PADDING;
$ctxt_os = openssl_encrypt($data."\0\0", 'BF-ECB', $key, $opts);
echo bin2hex($ctxt_mc).PHP_EOL;
echo bin2hex($ctxt_os).PHP_EOL;
дает:
e73d2adf1367a24c
e73d2adf1367a24c
В качестве альтернативы, вручную добавляя байты заполнения PKCS # 5 в конце при использовании mcrypt
:
$key = "supersecretkey";
$data = "foobar";
$ctxt_mc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data."\2\2", MCRYPT_MODE_ECB);
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY;
$ctxt_os = openssl_encrypt($data, 'BF-ECB', $key, $opts);
echo bin2hex($ctxt_mc).PHP_EOL;
echo bin2hex($ctxt_os).PHP_EOL;
дает
d73caa6afabbb029
d73caa6afabbb029
Наконец, попытка вызвать openssl_encrypt()
с отключенным заполнением и длиной, не кратной размеру блока:
$key = "supersecretkey";
$data = "foobar";
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY | OPENSSL_ZERO_PADDING;
$ctxt = openssl_encrypt($data, 'BF-ECB', $key, $opts);
echo(openssl_error_string().PHP_EOL)
дает
error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length
Примечание: имя OPENSSL_ZERO_PADDING
сбивает с толку, но это означает "без заполнения".Вы можете испытать желание использовать флаг OPENSSL_NO_PADDING
, но этот флаг не предназначен для использования с openssl_encrypt()
.Его значение равно 3 , что равно OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
.Вместо этого предназначен для использования с асимметричной криптографией .