Заменить Mcrypt на OpenSSL - PullRequest
       24

Заменить Mcrypt на OpenSSL

18 голосов
/ 03 апреля 2012

В настоящее время в наших системах есть реализация mcrypt для шифрования некоторых полезных данных в нашем PHP-приложении. Теперь у нас есть новое требование, чтобы мы изменили модуль crypt на openssl. Также важно знать, что мы используем шифр blowfish и режим ecb. Поэтому я начал тестировать различия и то, как я могу расшифровать зашифрованные строки mcrypt с помощью openssl.

Я использовал стандартную функцию PHP:

  • mcrypt_encrypt vs. openssl_encrypt
  • mcrypt_decrypt vs. openssl_decrypt

Оба метода дают разные результаты. Второе - это то, что в данном шифре (blowfish) и режиме (ecb) в обоих типах требуются разные длины IV (openssl = 0 и mcrypt = 56).

Кто-нибудь знает, как я могу легко изменить модули без больших усилий по миграции?

Заранее спасибо!

UPDATE:

Вот код, который я проверял:

<code><?php 

function say($message){
    if(!is_string($message)){
        if(!isset($_SERVER["HTTP_USER_AGENT"])) echo "<pre>";
        echo var_export($message, true) . ((!isset($_SERVER["HTTP_USER_AGENT"]) ? "\n" : "<br />"));
        if(!isset($_SERVER["HTTP_USER_AGENT"])) echo "
"; } Еще { echo $ message. ((! isset ($ _ SERVER ["HTTP_USER_AGENT"])? "\ n": "
")); } } сказать ("= Начать сырое шифрование"); $ key = "anotherpass"; $ str = "это работает"; сказать («Params:»); say ("- строка для шифрования". $ str. "'"); сказать ("- ключ:". $ ключ); сказать(""); $ params = array ( "openssl" => массив ( "cipher" => "BF", "mode" => "ECB", ), "mcrypt" => массив ( "cipher" => "blowfish", "mode" => "ecb", ), ); сказать ("= Mcrypt"); $ handler = mcrypt_module_open ($ params ['mcrypt'] ['cipher'], '', $ params ['mcrypt'] ['mode'], ''); $ iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($ handler), MCRYPT_RAND); $ keysize = mcrypt_enc_get_key_size ($ handler); mcrypt_generic_init ($ Обработчик, $ ключ, "\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0"); сказать («Params:»); say ("- InitVector" .bin2hex ($ iv). "(bin2hex)"); say ("- Максимальный размер ключа". $ keysize); say ("- Cipher". $ params ['mcrypt'] ['cipher']); say ("- Mode". $ params ['mcrypt'] ['mode']); сказать(""); сказать («Шифрование:»); $ m_encrypted = mcrypt_generic ($ handler, $ str); $ m_decrypted = mdecrypt_generic ($ handler, $ m_encrypted); say ("- Зашифровано" .bin2hex ($ m_encrypted). "(bin2hex)"); сказать ("- Расшифровано". $ m_decrypted); сказать(""); сказать ("= Openssl"); сказать («Params:»); сказать («- InitVector не требуется»); say ("- Макс. размер ключа" .openssl_cipher_iv_length ($ params ['openssl'] ['cipher']. "-". $ params ['openssl'] ['mode'])); say ("- Cipher". $ params ['openssl'] ['cipher']); say ("- Mode". $ params ['openssl'] ['mode']); сказать(""); сказать («Шифрование:»); $ o_encrypted = openssl_encrypt ($ str, $ params ['openssl'] ['cipher']. "-". $ params ['openssl'] ['mode'], $ key, true); $ o_decrypted = openssl_decrypt ($ o_encrypted, $ params ['openssl'] ['cipher']. "-". $ params ['openssl'] ['mode'], $ key, true); say ("- Зашифровано" .bin2hex ($ o_encrypted). "(bin2hex)"); сказать ("- Расшифровано". $ o_decrypted);

И вот мой результат:

= Begin raw encryption
  Params:
  - String to encrypt 'does it work'
  - Key: anotherpass

= Mcrypt
  Params:
  - InitVector   06a184909d7bf863 (bin2hex)
  - Max keysize  56
  - Cipher       blowfish
  - Mode         ecb

  Encryption:
  - Encrypted   0e93dce9a6a88e343fe5f90d1307684c (bin2hex)
  - Descrypted  does it work

= Openssl
  Params:
  - InitVector   not needed
  - Max keysize  0
  - Cipher       BF
  - Mode         ECB

  Encryption:
  - Encrypted   213460aade8f9c14d8d51947b8231439 (bin2hex)
  - Descrypted  does it work

Может быть, есть какие-нибудь идеи сейчас?

Спасибо!

Ответы [ 4 ]

10 голосов
/ 03 ноября 2013

Blowfish - блочный шифр.Это требует дополнения данных перед шифрованием.OpenSSL использует PKCS # 7, а mcrypt использует PKCS # 5.Различные алгоритмы заполнения для данных.Минимальная длина отступа PKCS # 5 равна 0, для PKCS # 7 - 1 ( wikipedia ).Взгляните на этот пример (я вручную дополнил входные данные для mcrypt_encrypt() в стиле PKCS # 7):

<?php 

$key = "anotherpassword1";
$str = "does it work 12";

$enc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $str."\1", MCRYPT_MODE_ECB);
$dec = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $enc, MCRYPT_MODE_ECB);
echo(bin2hex($enc).PHP_EOL);
var_dump($dec);

$enc = openssl_encrypt($str, 'bf-ecb', $key, true);
$dec = openssl_decrypt($enc, 'bf-ecb', $key, true);
echo(bin2hex($enc).PHP_EOL);
var_dump($dec);

?>

Невозможно открыть данные openssl_decrypt (), зашифрованные с помощью mcrypt_encrypt (), если только данные вручнуюзаполнение было выполнено с помощью PKCS # 7 до вызова mcrypt_encrypt().

В вашем случае есть только один способ - повторно скопировать данные.

PS: в вашем источнике есть ошибка - ECBрежим вообще не использует IV ( wikipedia )

2 голосов
/ 08 июля 2018

Если вы хотите зашифровать с помощью openssl и по-прежнему получить тот же результат, как если бы вы зашифровали его с помощью mcrypt при дешифровании с помощью mcrypt, вам нужно вручную обнулить входную строку до того, как зашифровать ее с помощью openssl_encrypt, и передать OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING варианты.

$str = 'encrypt me';
$cipher = 'AES-256-CBC';
$key = '01234567890123456789012345678901';
$opts = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
$iv_len = 16;
$str_len = mb_strlen($str, '8bit');
$pad_len = $iv_len - ($str_len % $iv_len);
$str .= str_repeat(chr(0), $pad_len);
$iv = openssl_random_pseudo_bytes($iv_len);


$encrypted = openssl_encrypt($str, $cipher, $key, $opts, $iv);

Расшифровка с помощью mcrypt_decrypt будет работать так же, как если бы вы также использовали mcrypt для шифрования.

mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv)
1 голос
/ 08 марта 2018

Для более коротких ключей вы должны делать циклические ключи для openssl при переносе blowfish mcrypt.

function make_openssl_blowfish_key($key)
{
    if("$key" === '')
        return $key;

    $len = (16+2) * 4;
    while(strlen($key) < $len) {
        $key .= $key;
    }
    $key = substr($key, 0, $len);
    return $key;
}

См .: https://bugs.php.net/bug.php?id=72362

См .: Переход от mcrypt с Blowfish &ЕЦБ в OpenSSL

0 голосов
/ 09 марта 2018

@ clover правильно, что отступы по умолчанию для Blowfish отличаются между mcrypt и Openssl, но неправильно, что это невозможно сделать.Если вы используете опцию OPENSSL_ZERO_PADDING для дешифрования, то они фактически совместимы:

openssl_decrypt($data, 'bf-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
...