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

Зашифрованные результаты Java и С++ не совпадают

У меня есть код С++, который будет шифровать строку. Теперь я сделал то же шифрование.   Некоторые из зашифрованных строк соответствуют. Некоторые из них не соответствуют одному или двум символам.

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

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

java:

U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQ * Pw * yV15HEoyECBeAZ6MTeN + ZYHRitKanY5jiRU2J0KP0Fzola

С++:

U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQ * JQ * yV15HEoyECBeAZ6MTeN + ZYHRitKanY5jiRU2J0KP0Fzola

Я использую шифрование AES. провайдер SunJCE версии 1.6. Я попробовал сменить поставщика на Bouncy Castle. Даже тогда результат такой же.

Добавлен один вариант:

С++:

U2FsdGVkX18xMjM0NTY3O * я */BMu11HkHgnkx + dLPDU1lbfRwb + aCRrwkk7e9dy ++ MK +/94dKLPXaZDDlWlA3gdUNyh/FXV * из * STgl3QgpS0XU =

Java:

U2FsdGVkX18xMjM0NTY3O * D */BMu11HkHgnkx + dLPDU1lbfRwb + aCRrwkk7e9dy ++ MK +/94dKLPXaZDDlWlA3gdUNyh/FXV * j9 * STgl3QgpS0XU =

UPDATE:

В соответствии с комментариями я считаю, что шифрование 64-го уровня является виновником. Я использую Latin-1 char в обоих местах. Что-нибудь еще, что я могу проверить

4b9b3361

Ответ 1

Вздох!!

Проблема почти наверняка заключается в том, что после шифрования данных и получения зашифрованных данных в виде строки byte вы делаете какое-то преобразование символов в данных перед отправкой через преобразование Base-64.

Обратите внимание, что если вы зашифруете строки "ABCDEFG" и "ABCGEFG", зашифрованный вывод будет совершенно другим, начиная с 4-го символа и продолжая до конца. Другими словами, выходы Base-64 были бы чем-то вроде (с использованием затененных значений):

U2FsdGVkX18xMj

и

U2FsdGXt91mJpz

Тот факт, что в приведенных выше примерах только два изолированных символа Base-64 (один байт) испорчены в каждом случае, в значительной степени доказывает, что коррупция происходит после шифрования.

Результатом процесса шифрования является последовательность byte, а не последовательность символов. Наблюдаемая коррупция согласуется с ошибочным интерпретацией байтов как символов и попыткой выполнить преобразование кодовой страницы на них, прежде чем подавать их в конвертер Base-64. Выход из шифровального устройства должен быть подан непосредственно в конвертер Base-64 без каких-либо преобразований.

Вы говорите, что используете "Latin-1 char, установленный в обоих местах", явный признак того, что вы делаете какое-то преобразование, которого вы не должны делать - не должно быть необходимости гадать с наборами char.

Ответ 2

Сначала немного кода:

import javax.xml.bind.DatatypeConverter;

...

public static void main(String[] args) {
    String s1j = "U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQPwyV15HEoyECBeAZ6MTeN+ZYHRitKanY5jiRU2J0KP0Fzola";
    String s1c = "U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQjQyV15HEoyECBeAZ6MTeN+ZYHRitKanY5jiRU2J0KP0Fzola";
    byte[] bytesj = DatatypeConverter.parseBase64Binary(s1j);
    byte[] bytesc = DatatypeConverter.parseBase64Binary(s1c);
    int nmax = Math.max(bytesj.length, bytesc.length);
    int nmin = Math.min(bytesj.length, bytesc.length);
    for (int i = 0; i < nmax; ++i) {
        if (i >= nmin) {
            boolean isj = i < bytesj.length;
            byte b = isj? bytesj[i] : bytesc[i];
            System.out.printf("%s [%d] %x%n", (isj? "J" : "C++"), i, (int)b & 0xFF);
        } else {
            byte bj = bytesj[i];
            byte bc = bytesc[i];
            if (bj != bc) {
                System.out.printf("[%d] J %x != C++ %x%n", i, (int)bj & 0xFF, (int)bc & 0xFF);
            }
        }
    }
}

Это обеспечивает

[60] J 3f != C++ 8d

Теперь 0x3f - это код вопросительного знака.

Ошибка заключается в том, что 0x80 - 0xBF находятся в латинском-1, официально ISO-8859-1, управляющие символы. Windows Latin-1, официально Windows-1252, использует эти коды для других символов.

Следовательно, вы должны использовать "Windows-1252" или "Cp1252" (кодовая страница) в Java.


Blundly

В шифровании исходные байты в диапазоне 0x80.. 0xBF были заменены вопросительным знаком из-за некоторого перевода в ISO-8859-1 вместо Windows-1252 на байт [].