Получение мусора после шифрования tripledes_cbc по схеме NoPadding

Я делаю расшифровку некоторых зашифрованных данных. Скажем, данные являются строго конфиденциальной информацией. Информация шифруется алгоритмом tripledes_cbc. Секретный ключ, используемый для шифрования информации, зашифрован алгоритмом rsa.

Но когда я пытаюсь расшифровать информацию с помощью алгоритма DESede/CBC/NoPadding, я получаю исходные данные вместе с некоторыми символами мусора, добавленными в начале и в конце.

Когда я пытаюсь использовать DES/CBC/PKCS5Padding вместо DESede/CBC/NoPadding, я получаю исключение «последний блок неправильно заполнен».

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

        KeyStore ks = KeyStore.getInstance("jks");
        FileInputStream fis = new FileInputStream(ksFile);
        ks.load(fis, "testing".toCharArray());

        PrivateKey privateKey = (PrivateKey) ks.getKey("keys", "1234".toCharArray());

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] kekBytes = cipher.doFinal(Base64.decodeBase64(encKey.getBytes("UTF-8")));

        SecureRandom random = new SecureRandom();
        byte[] iv = new byte[8];
        random.nextBytes(iv);

        SecretKey key = new SecretKeySpec(kekBytes, "DESede");
        Cipher cipher1 = Cipher.getInstance("DESede/CBC/NoPadding");
        cipher1.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
        byte[] out = cipher1.doFinal(Base64.decodeBase64(data.getBytes("UTF-8")));

        System.out.println("Data Length: " + out.length);
        String result = new String(out, "UTF-8");

person K.Nath    schedule 27.10.2017    source источник
comment
1. 3DES не следует использовать для новой работы, в настоящее время используется симметричный метод AES. Но я предполагаю, что это школьный проект, а школы отстают от реального мира примерно на десять лет. 2. Приведите пример ожидаемых и расшифрованных данных в шестнадцатеричном формате.   -  person zaph    schedule 27.10.2017
comment
Очевидно, вам нужно выяснить, какое заполнение использовалось шифрующей стороной. Кроме того, вы используете DES или DESede? Потому что DES/CBC/PKCS5Padding не является разумной альтернативой DESede/CBC/NoPadding. Возможно, вы имели в виду DESede/CBC/PKCS5Padding?   -  person President James K. Polk    schedule 28.10.2017


Ответы (1)


Ваш ключ правильный, если правильная средняя часть. Блок в начале, вероятно, является IV, который был префиксом к зашифрованному тексту. Если вы попытаетесь расшифровать это, вы получите мусор. После этого сам IV берется в качестве вектора для следующего блока, поэтому шифр CBC успевает исправить себя и продолжает работать правильно. Теоретически: CBC имеет ограниченное распространение ошибок.

Часть в конце - это используемая схема заполнения. Вы должны попробовать "DESede/CBC/PKCS5Padding". Если это не сработает, вам нужно взглянуть на двоичные значения (действительно, например, в шестнадцатеричном кодировании) и выяснить схему заполнения, которая используется, чтобы вы могли распаковать свои данные.

Обратите внимание, что в стандартных поставщиках криптографии для Java не так много схем заполнения. Таким образом, вам нужно либо найти провайдера, который предоставляет, например. битовое заполнение или вы можете использовать "NoPadding" и выполнить распаковку самостоятельно.

Если это для онлайн-протокола, возможно, пришло время узнать об атаках оракула заполнения и, действительно, о более современных протоколах, таких как AES/GCM и RSA/OAEP.

person Maarten Bodewes    schedule 27.10.2017
comment
Как определить заполняющие символы из шестнадцатеричного представления расшифрованного сообщения? Шестнадцатеричный результат выглядит следующим образом (здесь приведены только первые и последние несколько символов): - person K.Nath; 28.10.2017
comment
@K.Nath С учетом некоторых непреднамеренных невидимых символов в приведенных выше данных в шестнадцатеричном кодировании формат представляет собой 8-байтовую преамбулу, за которой следует текст в кодировке ASCII, за которым следуют 8-байтовые данные. Почему вы считаете, что это неправильно? - person zaph; 28.10.2017
comment
@zaph - я не имел в виду, что вывод был неверным. Я просто хотел извлечь текст, за исключением мягкого мусора. Я мог бы преодолеть мусор, заполненный в начале выходной строки, удалив первые 16 символов (в приведенном выше комментарии - '5368f1b5beaa10ec'), поскольку я вижу, что первые 16 символов всегда отличаются каждый раз, когда я запускаю код Java. Но я не могу удалить мусор из хвоста выходной строки, поскольку, за исключением первых 16 символов, как уже упоминалось, все остальные символы остаются неизменными каждый раз, когда я запускаю код Java. - person K.Nath; 28.10.2017
comment
@ K.Nath, так что это не проблема расшифровки, а просто проблема манипулирования байтами. Кажется, что то, что вы хотите, всегда заканчивается символом › (0x3e), поэтому просто найдите первый › с конца и удалите его. - person zaph; 28.10.2017
comment
Вероятно, это заполнение ISO, что означает, что количество байтов заполнения закодировано в последнем байте. - person Maarten Bodewes; 28.10.2017
comment
@MaartenBodewes Отлично, еще проще! Я видел 0x08, но не знаком с заполнением ISO. - person zaph; 28.10.2017
comment
@zaph Это старый режим заполнения, который сейчас практически не используется. У него много недостатков заполнения ISO с дополнительной проблемой, заключающейся в том, что предыдущие байты должны быть случайными (или любыми значениями, но обычно случайными). Конечно, необходимость запрашивать дополнительные байты у PRNG не очень эффективна; PRNG часто намного менее эффективен, чем сам блочный шифр, и часто требует обращения к ОС. Tnx за ссылку, был на мобильном телефоне в клубе каякинга. - person Maarten Bodewes; 28.10.2017