Почему mcrypt и openssl_encrypt не дают одинаковых результатов для blowfish с ecb, если пароль короче 16 символов? - PullRequest
0 голосов
/ 14 января 2019

Я прочитал общие предложения: mcrypt устарел, какова альтернатива? и PHP7.1 альтернатива mcrypt

И протестированы следующие решения: Перенос mcrypt с Blowfish и ECB в OpenSSL и php: mcrypt_encrypt to openssl_encrypt и проблемы OPENSSL_ZERO_PADDING

Они не работают. Это мой используемый код:

$message = "My secret message";
$key = "mysecretpasswor"; // <- if you add one more character here, it's working
$iv = "\0\0\0\0\0\0\0\0";

$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_BLOWFISH, $key, $message, MCRYPT_MODE_ECB, $iv);
$encrypted_openssl = openssl_encrypt($message_padded, "bf-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING);

printf("%s => %s\n", $message, base64_encode($encrypted_mcrypt));
printf("%s => %s\n", $message_padded, base64_encode($encrypted_openssl));

Использование чего-то вроде "DES-EDE3-CBC" в качестве метода шифрования работает. Но я не могу изменить используемое шифрование. Я должен перенести старый код в новый код. Иногда используются ключи длиной не более 16 символов.

Есть предложения?

1 Ответ

0 голосов
/ 15 января 2019

Прежде всего, OPENSSL_NO_PADDING не должен использоваться с openssl_encrypt(). В документации упоминается OPENSSL_ZERO_PADDING, что (смущает) означает «без заполнения». Это то, что вы хотите.

OPENSSL_NO_PADDING - , предназначенный для использования с асимметричной криптографией . По совпадению он имеет значение 3, равное OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING. Это причина, по которой вы можете использовать его неправильно, без последствий (в данном случае).

Ваши шифротексты отличаются, потому что функция openssl_encrypt() в режиме bf-ecb по умолчанию дополнит вашу клавишу ключом \0, если его длина меньше 16 байтов. Это не требуется для blowfish, и mcrypt_encrypt() этого не делает. Чтобы отключить это поведение, используйте флаг OPENSSL_DONT_ZERO_PAD_KEY при вызове openssl_encrypt(). Поскольку этот флаг, похоже, не задокументирован, вам нужно перейти к исходному коду , чтобы узнать об этом :-). Или прочитайте Ошибка # 72362 Шифрование OpenSSL Blowfish некорректно для коротких ключей .

При этом правильный вызов openssl_encrypt() становится:

$opts = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING | OPENSSL_DONT_ZERO_PAD_KEY;
$encrypted_openssl = openssl_encrypt($message_padded, "bf-ecb", $key, $opts);

Тестирование:

$ php bf.php
My secret message => JPO/tvAqFD2KCTqfv0l8uWLfPUWdZIxQ
My secret message => JPO/tvAqFD2KCTqfv0l8uWLfPUWdZIxQ
...