#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.