Зашифрованные результаты 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 в обоих местах. Что-нибудь еще, что я могу проверить
Ответы
Ответ 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 на байт [].