mcrypt шифрует, добавляя связку » в конец строки

#php #encryption #padding #mcrypt

#php #шифрование #заполнение #mcrypt

Вопрос:

Работа с OAuth и шифрование ключей с помощью следующей функции с помощью строки, которую мы будем называть ‘foo’ (фактически токен OAuth)

 public function encrypt( $text )
{
    // add end of text delimiter
    $data = mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, $this->iv );
    return base64_encode( $data );
}
  

Когда я расшифровываю ее с помощью обратной функции, я получаю:

Функция:

     public function decrypt( $text )
    {
        $text = base64_decode( $text );
        return mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, $this->iv );
    }
  

Результат:

foo

Редактировать:

Посмотрев на это немного подробнее, я понял, что на самом деле это кодировка URL в , что означает, что мои строки каким-то образом дополняются нулевыми символами? Итак, в настоящее время я использую trim (), чтобы избавиться от них, но я хотел бы понять, почему это происходит.

Комментарии:

1. все с точностью до наоборот. Редактирование для отображения.

Ответ №1:

Rijndael является блочным шифром, что означает, что он работает с фрагментами данных определенной длины (в данном случае 128 бит). Это означает, что если длина входного текста не кратна размеру блока, его необходимо дополнить, чтобы он соответствовал размеру. В этом случае заполнением являются нули; существует ряд других возможных схем заполнения, которые можно использовать, но если вы хотите использовать их с помощью PHP mcrypt, вам придется применять их вручную.

Комментарии:

1. Заполнение по умолчанию (и единственное, которое поддерживается mcrypt внутренне) — это NULL заполнение (не 0 ). Это NULL символ x00 в кодировке URL.

2. @SteanGehrig: «нули» могут означать символ U 0030 или символ U 0000.

3. @Anomie оба варианта были бы неправильными, потому что мы говорим о байтах с этим значением, а не о символах.

Ответ №2:

Вы можете исправить это с помощью этого метода, чтобы избавиться от символов заполнения: в нашем случае мы используем Zend.

 $filter = new Zend_Filter_Decrypt(array('adapter' => 'mcrypt'));
$filter->setVector($lpt->_seed);
str_replace("x0", '', trim($filter->filter(base64_decode($textToDecrypt))));
  

Комментарии:

1. Похоже, что это удаляет все 0x00 байт, а не только 0x00 байт заполнения. Вам действительно следует просто использовать rtrim($decrypted, "") .

Ответ №3:

MCRYPT_MODE_ECB означает, что вы используете ECB, режим работы блочного шифрования. Блочные шифры могут обрабатываться либо для режимов работы с блочным шифром, либо для режимов работы с потоковым шифром. Распространенными режимами блочного шифрования являются ECB и CBC, распространенным режимом потокового шифрования является CTR, более известный как режим работы счетчика.

MCRYPT_RIJNDAEL_128 является реализацией AES. AES — это шифр Rijndael с размером блока 128 бит и тремя возможными размерами ключа: 128, 192 и 256 бит. Итак, если вы используете режим шифрования с блочным шифрованием, вам нужно разделить обычный текст размером 128 бит — по 16 байт — каждый. Конечно, это оставляет вас с вопросом, что делать, когда последний блок не равен 16 байтам.

В PHP mcrypt_encrypt это более или менее остается на усмотрение пользователя. Она дополняется 00 значными символами, если блок не заполнен до размера блока. Это нормально, если входные данные представляют собой строку; вы можете просто trim убрать 00 символы из возвращаемой строки. Однако, если входные данные представляют собой двоичные данные, которые заканчиваются 00 символом, то этот символ теряется ( любой другой символ, который берется из начала и конца строки, конечно). Вы также можете отправить длину строки в зашифрованном виде вместе с открытым текстом, конечно.

Для лучшей схемы вам нужно только взглянуть на заполнение PKCS # 7. Несколько фрагментов кода для реализации заполнения можно найти в разделе комментариев mcrypt_encrypt .

mcrypt_encrypt в настоящее время, похоже, не поддерживает режимы потока для AES, так что эта опция недоступна, если вы хотите сохранить библиотеку PHP mcrypt.