Подтвердить что ты не робот

Почему выход Blowfish в Java и PHP отличается только двумя символами?

У меня есть шифрование blowfish script в PHP и JAVA наоборот, который работал нормально до сегодняшнего дня, когда я столкнулся с проблемой.

То же самое содержимое зашифровывается по-разному в Java vs PHP всего за 2 символа, что действительно странно.

PHP

wTHzxfxLHdMm/JMFnoh0hciS/JADvFFg

Java

wTHzxfxLHdMm/JMFnoh0hciS/D8DvFFg
-------------------------^^

Как вы видите, эти две позиции не совпадают. К сожалению, это реальный адрес электронной почты, и я не могу поделиться им. Также я не смог воспроизвести проблему с другими немногими значениями, которые я тестировал. Я попытался изменить классы кодирования Base64 на Java, и это не помогло.

Исходный код PHP здесь, а для Java здесь.

Что я могу сделать для решения этой проблемы?

4b9b3361

Ответ 1

Посмотрим на код Java:

String c = new String(Test.encrypt((new String("thevalue")).getBytes(),
                                   (new String("mykey")).getBytes()));
...
System.out.println("Base64 encoded String:" +
                   new sun.misc.BASE64Encoder().encode(c.getBytes()));

Что вы здесь делаете:

  • Преобразование строки открытого текста в байты с использованием системного кодирования по умолчанию
  • преобразовать ключ в байты, используя стандартную кодировку системы
  • зашифровать байты
  • преобразовать зашифрованные байты в строку, используя стандартную кодировку системы
  • преобразовать зашифрованную строку обратно в байты, используя системное кодирование по умолчанию
  • закодируйте эти зашифрованные байты с помощью Base64.

Проблема заключается в шаге 4. Предполагается, что произвольный массив байтов представляет собой строку в вашей системе по умолчанию, а кодировка этой строки возвращает тот же байт []. Это справедливо для некоторых кодировок (например, серия ISO-8859), но не для других. В Java, когда некоторый байт (или байтовая последовательность) не представляется в данной кодировке, он будет заменен другим символом, который позже для преобразования будет отображаться в байт 63 (ASCII ?). На самом деле в документации даже говорится:

Поведение этого конструктора, когда данные байты недопустимы в кодировке по умолчанию, не указывается.

В вашем случае нет оснований делать это вообще - просто используйте байты, которые ваш метод encrypt выводит напрямую, чтобы преобразовать их в Base64.

byte[] encrypted = Test.encrypt("thevalue".getBytes(),
                                "mykey".getBytes());
System.out.println("Base64 encoded String:"+ new sun.misc.BASE64Encoder().encode(encrypted));

(Также обратите внимание, что я удалил лишние вызовы конструктора new String("...") здесь, хотя это не относится к вашей проблеме.)

Следует помнить: Никогда не преобразовывать произвольный байт [], который не был получен из кодировки строки, в строку. Вывод алгоритма шифрования (и большинства других криптографических алгоритмов, кроме дешифрование), безусловно, относится к категории данных, которые не должны быть преобразованы в строку.

И никогда не используйте кодировку System default, если вы хотите переносить программы.

Ответ 2

Ваш код мне кажется правильным.

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

Каждый из этих блоков 4 char представляет 3 символа в зашифрованной строке. Большая часть (JA и D8 в 7-м блоке) на самом деле происходит от одного другого символа.

wTHz xfxL HdMm/JMF noh0 hciS/JAD vFFg

wTHz xfxL HdMm/JMF noh0 hciS/D8D vFFg

Если у меня все получится, ваш адрес электронной почты будет длиться 19 символов. 20-й символ в одной из ваших строк ввода - это пробел.

Ответ 3

Вопрос. Пробовали ли вы связанную библиотеку расшифровки PHP с расшифровкой генерируемого PHP зашифрованного текста? Вы пробовали связанную библиотеку расшифровки JAVA для расшифровки зашифрованного текста JAVA?

Если оба выдают разные выходы, тогда один ДОЛЖЕН завершить дешифрование.

Это один PHP или Java?

Какой бы он ни был - я попытался бы дублировать другой такой сбой с общедоступной строкой... передать эту строку как unit test - разработчику или разработчикам, которые создали код шифрования/дешифрования на языке что шифрование/расшифровка в оба конца не выполняется.

Затем... дождитесь их исправления.

Не уверены в каких-либо более быстрых решениях - за исключением, может быть, замены поставщиков библиотеки шифрования/расшифровки... или сворачивания собственных...