Неверный размер ключа при переносе шифрования Crypto ++ AES на PHP mcrypt - PullRequest
2 голосов
/ 29 октября 2010

Раньше мне удалось перенести код CBC CryptoPP Rijndael_128 CBC на MCrypt PHP, но теперь у меня проблемы с режимом CFB.Результаты C ++ и PHP не совпадают (хорошо, первый байт соответствует, но это может быть совпадением, все остальное не совпадает).С некоторой диагностикой, похоже, что PHP mcrypt неправильно устанавливает длину ключа?

Вот C ++ (диагностика и вся информация удалена для простоты):

CFB_Mode<AES>::Encryption encryptor(g_encrypt_key, AES::DEFAULT_KEYLENGTH, g_encrypt_iv);

StringSource ss( sInput.c_str(), true, 
        new StreamTransformationFilter( encryptor, 
            new HexEncoder( new StringSink( sEncryptedOut ) )
        ));

А вот PHP: *Длина 1006 *

$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CFB, '')
mcrypt_generic_init($cipher, $g_encrypt_key, $g_encrypt_iv);

$sEncryptedOutput = mcrypt_generic( $cipher, $sInput);
mcrypt_generic_deinit($cipher);
mcrypt_module_close($cipher);

g_encrypt_key и g_encrypt_iv составляет 16 байтов, и байты совпадают для версий C ++ и PHP.Для версии PHP это двоичная строка, построенная из байтов (да, я проверил, что они идентичны).

Я добавил вызовы в версию PHP, чтобы проверить размер блока $cipher, размер ключа,и т. д. Размер блока и размер iv - 16;поддерживаемые размеры ключей указаны как 16, 24 и 32 - все как и ожидалось.

В чем проблема, я думаю, что размер ключа сообщается как 32 байта.Глядя на документы mcrypt, единственный способ установить размер ключа - это предоставить ключ нужного размера.Но я передаю 16-байтовый ключ!Так почему же он сообщает о наличии 32-байтового ключа?Если режим CFB должен использовать 32-байтовый ключ, то почему CryptoPP принимает его как нормальный?Каково решение?Могу ли я заставить PHP использовать предоставленный 16-байтовый ключ?Или я пропускаю параметр, который по умолчанию отличается от CryptoPP, отличного от MCrypt?

Я использую режим CFB, потому что хочу минимизировать длину результирующих зашифрованных данных.Несколько байтов, которые вводит заполнение, имеют значение в этом приложении.

Мне нужно иметь возможность шифровать / дешифровать в C ++, но только в PHP.AES, возможно, является излишним для моего приложения - минимум, который мне нужен, - это «хорошее скремблирование байтов», чтобы функция отдельных байтов в данных не была очевидной.

Ответы [ 3 ]

4 голосов
/ 29 октября 2010

Это было некоторое время, но у меня были некоторые похожие проблемы с mcrypt и openSSL, использующими CFB пару лет назад. В конце я обнаружил, что mcrypt использовал другой размер цепочки обратной связи по умолчанию, чем openssl в режиме CFB. То есть, я считаю, что openSSL AES128 в CFB использовал размер блока и размер обратной связи 128 бит, в то время как mcrypt использовал размер блока 128 бит и размер обратной связи 8 бит. У меня нет возможности это подтвердить, в то время это были просто предположения, основанные на прочтении некоторых старых сообщений на форуме. Независимо от истинности этой теории, я был не единственным человеком или первым, кто столкнулся с этой конкретной проблемой.

Решением для меня было использовать nOFB как себя. Согласно справочному файлу PHP mcrypt MCRYPT_MODE_NOFB заставляет цепочку обратной связи равняться размеру блока алгоритма, в данном случае 128-битный блок / обратная связь для AES128 (Rijndael), что соответствует тому, что Страница man для модуля mcrypt сообщает о nOFB. Это хорошо, так как все, что я нашел, говорит, что обратная связь nOFB синхронна с размером блока. Таким образом, и mcrypt, и OpenSSL в nOFB теперь были 128-битными размерами ключа / iv / block / feedback for AES128, и все работало нормально.

Поскольку PHP сообщает о 256-битных размерах ключей (32 байта), функция, которая возвращает текущий размер ключа алгоритма шифрования, фактически возвращает максимальный размер ключа, что явно не указано в документации. Я знаю это, потому что мой маленький класс, который я сейчас использую для различных проектов, прекрасно работает с openSSL и любыми другими библиотеками AES в CBC или nOFB. Это было бы не так, если бы mcrypt дополнял мой 128-битный (16-ти символьный) ключ дополнительными 128-битными пустыми строками или чем-то еще, и в любом случае не был бы технически корректным.

Не очень хороший ответ, но лучшее, что я получил, основано на очень любительском набеге на криптографию несколько лет назад.

2 голосов
/ 04 ноября 2010

Проверьте phpseclib:

http://phpseclib.sourceforge.net/

Вы можете установить размер ключа и размер блока на любое значение.

например. $ aes-> setKeyLength (128) или $ aes-> setKeyLength (256);

1 голос
/ 03 февраля 2013

У меня была эта проблема - пара баллов.По умолчанию режим PHP Rijndael устанавливает цикл обратной связи равным 8 битам - чтобы AES была такой же длины, как и IV / Key.

Вы можете сделать это, используя режим 'ncfb' вместо 'cfb'или MCRYPT_MODE_CFB.

Полная информация о написании PHP, совместимого с aes_cfb_128, содержится в этом вопросе об обмене стеком безопасности: aes cfb 128 Проблема дешифрования / шифрования между Erlang и PHP .Суть в том, что (от Тома Лика):

... для CFB и OFB (которые отличаются друг от друга и не могут использоваться взаимозаменяемо), вам нужно беспокоиться о "обратной связидлина ", которая не обязательно задокументирована с высокой ясностью в различных криптографических библиотеках.И шифрование, и дешифрование должны использовать одинаковую длину обратной связи для взаимодействия.

...