Выяснение точного ключа, созданного PHP mcrypt

Приложение PHP, которое я поддерживаю, использует Rijndael_256 с шифрованием EBC_MODE с помощью mcrypt. Забавно, что ключ имеет длину не 256 бит, а всего 160. Согласно mcrypt_encrypt ключ дополняется \0, чтобы получить требуемый размер, если он слишком мал.

Ключ, с помощью которого данные будут зашифрованы. Если он меньше требуемого размера ключа, он дополняется «\0». Лучше не использовать строки ASCII для ключей.

Похоже, это происходит примерно в начале строки 1186. в mcrypt.c и изменив ключ в строке 1213.

Допустим, у нас есть $key = 'abcdefghijkm';, что слишком коротко, но реализация mcrypt в PHP обеспечивает расширение до 32 символов (или 256 бит) при использовании RIJNDAEL_256. Как будет выглядеть окончательный ключ?

Я спрашиваю об этом, потому что создается другое приложение, которое использует те же зашифрованные данные, но на другом языке. Perl, если быть точным, и я использую Crypto::Rijndael. Для данного примера ключа, какой точный ключ я должен передать Crypto::Rijndael (или любому другому, если на то пошло), чтобы иметь возможность снова расшифровать данные?

Обновить

С Perl я могу сгенерировать ключ, который дополнен \0, выполняя pack('a32', 'my secret key'); (или Z32), length() сообщит 32, а модуль Crypt::Rijndael примет ключ. Глядя на источник PHP mcrypt, это должен быть сгенерированный ключ (дополненный \ 0), но он просто не примет его.

Теоретически в PHP pack('a32', 'my secret key'); должен получиться тот же ключ с добавлением \0, который генерирует mcrypt в PHP, но это не так.

Я очень близок к тому, чтобы снова все зашифровать, но с новым ключом. Это занимает слишком много времени.


person Htbaa    schedule 18.07.2012    source источник
comment
Вы пробовали просто дополнить его 0s?   -  person MrGlass    schedule 18.07.2012
comment
Да и с этим не повезло.   -  person Htbaa    schedule 18.07.2012
comment
Помните, что результаты на самом деле могут быть непечатными символами, поэтому не полагайтесь на вывод консоли/страницы, чтобы определить, как на самом деле выглядит ключ. Но если вы запишете полученный ключ в двоичный файл, вы сможете вставить его в свой Perl-скрипт и успешно его использовать.   -  person Crontab    schedule 18.07.2012
comment
Я пробую это с обычным текстом, который был зашифрован с помощью PHP mcrypt_encrypt и пытался расшифровать с помощью Perl Crypt::Rijndael. Все, что мне нужно знать, это то, как выглядит фактический ключ, когда PHP mcrypt_encrypt делает с ним :-).   -  person Htbaa    schedule 18.07.2012
comment
Извините, что не отвечаю на вопрос напрямую, но я думаю, что это плохая идея. Если ваш ключ является паролем, сначала растяните значение с помощью KDF (например, PBKDF2, bcrypt, scrypt), а затем используйте результат для шифрования данных.   -  person Chris Smith    schedule 22.07.2012
comment
Не могли бы вы объяснить, что означает KDF? Тип данных, которые шифруются здесь, не имеет значения. Дело в том, что мне приходится иметь дело с данными, зашифрованными таким образом, и мне нужно иметь возможность расшифровать их, используя другой язык, в данном случае Perl.   -  person Htbaa    schedule 23.07.2012


Ответы (2)


Проблема не в заполнении ключа, а в том, что вы используете два разных размера блока. В PHP использование MCRYPT_RIJNDAEL_256 использует размер блока... 256 бит. Однако в perl, использующем Crypt::Rijndael, они отмечают:

размер блока
Размер блока для Rijndael составляет 16 байт (128 бит), хотя на самом деле алгоритм поддерживает любой размер блока, кратный нашим байтам. 128 бит – это размер блока, указанный AES, и это все, что мы поддерживаем.

Таким образом, нет ключа, который позволит выполнять преобразование между этими разными алгоритмами. Вы можете переключиться на 128 бит в PHP:

<?
$key = "abcdefghijklmnopqrstuvwxyz";
$data = "Meet me at 11 o'clock behind the monument.";
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB, nil);
echo bin2hex($crypttext) . "\n";
// prints c613d1804f52f535cb4740242270b1bcbf85151ce4c874848fd1fc2add06e0cc2d26b6403feef4a8df18f7dd7f8ac67d
?>

Какой Perl может без проблем расшифровать с помощью Crypt::Rijndael:

use Crypt::Rijndael;
$key = "abcdefghijklmnopqrstuvwxyz\0\0\0\0\0\0";
$crypttext = "c613d1804f52f535cb4740242270b1bcbf85151ce4c874848fd1fc2add06e0cc2d26b6403feef4a8df18f7dd7f8ac67d";
$cipher = Crypt::Rijndael->new($key, Crypt::Rijndael::MODE_ECB());
print $cipher->decrypt(pack('H*', $crypttext));
# prints "Meet me at 11 o'clock behind the monument."

Или вы можете переключиться на другой модуль Perl, который поддерживает блоки большего размера, например, Crypt::Rijndael_PP. :

# Same PHP code except using MCRYPT_RIJNDAEL_256
# prints f38469ec9deaadbbf49bb25fd7fc8b76462ebfbcf149a667306c8d1c033232322ee5b83fa87d49e4e927437647dbf7193e6d734242d583157b492347a2b1514c

Перл:

use Crypt::Rijndael_PP ':all';
$key = "abcdefghijklmnopqrstuvwxyz\0\0\0\0\0\0";
$crypttext = "f38469ec9deaadbbf49bb25fd7fc8b76462ebfbcf149a667306c8d1c033232322ee5b83fa87d49e4e927437647dbf7193e6d734242d583157b492347a2b1514c";
print rijndael_decrypt(unpack('H*', $key), MODE_ECB, pack('H*', $crypttext), 256, 256);
# prints "Meet me at 11 o'clock behind the monument."
person blahdiblah    schedule 26.07.2012
comment
Спасибо, я уже начал думать, что размер блока как-то связан с этим, но еще не было времени, чтобы проверить это. Думаю, тогда я пойду с Crypt::Rijndael_PP. - person Htbaa; 27.07.2012
comment
Хм, хотя $key на самом деле имеет длину 256 бит, Crypt::Rijndael_PP по-прежнему добавляет к нему 0. Мне кажется, что в нем есть ошибка? - person Htbaa; 27.07.2012
comment
@Htbaa Crypt::Rijndael_PP не такой зрелый модуль, как Crypt::Rijndael, и имеет некоторые странности. Примечательно, что ему нужен не необработанный ключ, а представление шестнадцатеричной строки. Посмотрите мой пример с его использованием: вам нужно unpack необработанный ключ перед его передачей. - person blahdiblah; 27.07.2012
comment
Ах, я вижу, это действительно немного странно. Попробую. - person Htbaa; 29.07.2012

person    schedule
comment
Я доволен тем, что mcrypt_encrypt выполняет заполнение \0. Мне нужен точный ключ, чтобы я мог использовать его на другом языке программирования. Спасибо за упоминание 0x00, забыл об этом. Интересно, будет ли undef в Perl таким же (сомневаюсь). - person Htbaa; 18.07.2012
comment
Ну, это должно быть 32 символа. В этом примере алфавит 26, 32-26 = 6, поэтому вы должны добавить 6 нулей или 0x00 :) - person HamZa; 18.07.2012
comment
Форматирование сейчас испорчено. На самом деле $key1 и $key2 имеют одинаковую длину, поэтому mcrypt_encrypt по-прежнему заботится о заполнении. То же самое касается $key3. Так что неудивительно, что они дают один и тот же результат, так как для PHP все они содержат "abcdefghijklmnopqrstuvwxyz". - person Htbaa; 18.07.2012
comment
следовательно, последний ключ "abcdefghijklmnopqrstuvwxyz" . NULL . NULL . NULL . NULL . NULL . NULL; ... - person HamZa; 18.07.2012
comment
Также Warning: hex2bin(): Hexadecimal input string must have an even length. Все эти 3 примера делают одно и то же, они позволяют mcrypt_encrypt позаботиться о заполнении. Вы передаете ему ключ длиной 26 байт. - person Htbaa; 18.07.2012
comment
Это предупреждение связано с тем, что мой код испорчен xD ... Кроме того, я не снабжаю его ключом размером 26 байт. 1 NULL = 1 байт, поэтому, если вы добавите 6 NULL к ключу, это будет 32 байта, что точно делает PHP mcrypt_encrypt, я не знаком с PERL, но если вы добавите эти NULL, это должен быть тот же метод шифрования :) - person HamZa; 18.07.2012
comment
Попробуйте выполнить strlen() для сгенерированных ключей. Он сообщит 26 для всех из них, что не должно быть правильным в соответствии с тем, что вы говорите. - person Htbaa; 18.07.2012
comment
это действительно расстраивает, '\ 0' означает конец строки, было бы естественно, что strlen() не считает это строкой... - person HamZa; 19.07.2012
comment
Поскольку strlen() вычисляет длину строки в байтах, я ожидаю, что она также будет считать \0, так как это тоже байт. Поскольку мы еще не можем быть уверены, что PHP делает со строкой до того, как mcrypt изменит строку ключа, мы все еще не уверены, какой должна быть строка в конечном итоге. - person Htbaa; 19.07.2012