AES-128 OFB отличается использованием mcrypt (PHP) и pycryptodome (Python) - PullRequest
1 голос
/ 06 мая 2019

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Все приведенные здесь примеры небезопасны и не близки к тому, чтобы быть хорошей практикой. Используемый здесь код предназначен для использования в вызове CTF и содержит несколько уязвимостей.

Вот мое действительное беспокойство: результат шифрования с тем же ключом, iv, mode и padding с использованием mcrypt_encrypt приводит к другому шифру, чем при том же использовании Crypto.cipher AES в python 2.7, но только при использовании Режим OFB . Вот мой пример:

$key = 'SUPER_SECRET_KEY';
$iv = '0000000000000000';
$data = "this is a test";
$padding = 16 - (strlen($data) % 16);
$data .= str_repeat(chr($padding), $padding);
echo base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_OFB, $iv));

Результат: k8Ss4ytOUNvcG96tr+rHdA==

Теперь пример с питоном:

from Crypto.Cipher import AES
from base64 import b64encode

key = 'SUPER_SECRET_KEY'
iv  = '0'*16
data = "this is a test"
padding = 16 - (len(data) % 16)
data += chr(padding)*padding
print(b64encode(AES.new(key, AES.MODE_OFB, iv).encrypt(data)))

Результат: kzFpEHCJB+2k2498DhyAMw==

Это происходит только в режиме OFB. Если бы я изменил режим на CBC (и больше ничего не изменил), оба результата были бы идентичны. Есть идеи, что происходит?

РЕДАКТИРОВАТЬ: использование openssl_encrypt в PHP дает мне те же результаты, что и код Python. Это наводит меня на мысль, что в mcrypt_encrypt есть ошибка.

$key = "SUPER_SECRET_KEY";
$iv  = "0000000000000000";
$data = "this is a test";
$padding = 16 - (strlen($data) % 16);
$data .= str_repeat(chr($padding), $padding);
$cipher = openssl_encrypt($data, "aes-128-ofb", $key, $options=OPENSSL_RAW_DATA, $iv);
echo base64_encode($cipher) ."\n";

1 Ответ

4 голосов
/ 06 мая 2019

Я не уверен, почему вы пытаетесь что-то сделать в режиме mcrypt или OFB - оба взрыва из прошлого, которые большинство криптографов пытаются забыть.Также неясно, почему вы используете padding для потокового режима, если только вы не работаете с ошибкой PyCrypto (см. Ниже).


Чтобы прямо ответить на ваш вопрос, из документации PHP:

MCRYPT_MODE_OFB (выходная обратная связь, в 8-битном режиме) - режим потокового шифра, сравнимый с CFB, но может использоваться в приложениях, где распространение ошибок не допускается.Рекомендуется использовать режим NOFB, а не режим OFB.

вы, вероятно, должны использовать:

MCRYPT_MODE_NOFB (выходная обратная связь в n-битном режиме) сравнимо с режимом OFB, но работает с полным размером блокаалгоритма.

, где "N" перед "OFB" - это размер блока режима работы.


Нет такой документации ни для PyCrypto, PyCryptoDome, ни для OpenSSL.Однако, кажется, что они обрабатывают 128 бит за один раз (согласно отчету об ошибке PyCrypto), так как это неправильно требует получения полных блоков открытого текста по тем или иным причинам.


OFB создаст другой зашифрованный текст, еслииспользуется в 8-битном или 128-битном режиме - за исключением самого первого байта, который должен быть идентичным.8-битный режим - такой же взрыв из прошлого, как и mcrypt или OFB;он использует полное шифрование блока на байт (!), чтобы уменьшить распространение ошибок.

Если вам нужен режим потоковой передачи, используйте режим CTR или, предпочтительно, аутентифицированный шифр, такой как GCM(который использует режим CTR внизу).Это будет быстрее (чем 8-битный OFB) и более безопасным.

...