Почему моя реализация Simplified DES работает нормально в кодировке Cp1252, а не в UTF-8?

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

Eclipse: Использование кодировки UTF-8 в текстовом редакторе приводит к тому, что строки не работают должным образом, как я могу это исправить?

Я постараюсь максимально проанализировать свою проблему, чтобы дать вам четкое представление о том, что происходит.

У меня есть университетский проект, где я должен реализовать алгоритм упрощенного DES для образовательных целей. Этот алгоритм является алгоритмом шифрования, который использует 10-битный ключ для шифрования 8-битных данных.

В реализацию я хотел включить шифрование любой строки.

Поэтому я написал код для 8-битного шифрования, и он отлично работал для всех типов входных данных. Чтобы включить поддержку шифрования строк, я использовал функцию String.getBytes(), сохранил все байты строки внутри переменной byte[] data

и тогда я следовал этой логике:

int i;
for(i=0; i< data.length; i++)
    data[i] = encrypt(data[i]);

и для расшифровки я следовал этой логике:

int i;
for(i=0; i< data.length; i++)
    data[i] = encrypt(data[i]);

Вот фактический код в main функция

public static void main(String[] args){

    short K = (short) Integer.parseInt("1010010001",2);
    SDEncryption sdes = new SDEncryption(K); //K is the 10 bit key

    String test = "INFO BOB 57674";

    //let's encrypt the String test
    String enc = sdes.encrypt(test.getBytes());

    //let's decrypt the encrypted String of the initial String
    String dec = sdes.decrypt(enc.getBytes());
}

Используя кодировку по умолчанию Cp1252. Я попытался зашифровать строку и получил следующие результаты:

Initial Text: INFO BOB 57674
Encrypted Text: ÅO [áa[aá»j×jt
Decrypted Text: INFO BOB 57674

Чтобы видеть фактическое представление битов каждый раз, когда я шифрую и дешифрую данные, я создал следующую функцию для отображения всех данных каждой строки:

public void show(byte[] data){
    //εμφάνιση των 
    //note how the Greek letters aren't displayed at all under Cp1252

    int i;
    for(i=0;i<data.length;i++){

        short mask = (short) (1<<7); //10000000
        while(mask>0){
            if((data[i]&mask) == 0)
                System.out.print("0");
            else
                System.out.print("1");

            mask = (short) (mask >> 1);
        }
        if(i < data.length - 1){

            System.out.print(" ");
        }
    }
    System.out.println();
}

Итак, я получил следующие результаты:

Initial Text(binary): 01001001 01001110 01000110 01001111 00100000 01000010 01001111 01000010 00100000 00110101 00110111 00110110 00110111 00110100
Encrypted Text(binary): 11000101 01001111 00100000 01011011 11100001 01100001 01011011 01100001 11100001 10111011 01101010 11010111 01101010 01110100
Decrypted Text(binary): 01001001 01001110 01000110 01001111 00100000 01000010 01001111 01000010 00100000 00110101 00110111 00110110 00110111 00110100

Похоже, все работает, как ожидалось. Чтобы поддерживать греческие буквы в редакторе кода, мне пришлось изменить кодировку на UTF-8.

После повторного запуска я получил следующие результаты:

Initial Text: INFO BOB 57674
Encrypted Text: �O [�a[a�j�jt
Decrypted Text: ���NFO���BOB���7���74

Обратите внимание, что некоторые слова расшифрованного текста отображаются правильно, например NFO а также BOB, Мне кажется, что есть какие-то проблемы с битовой манипуляцией, как будто Eclipse не распознает последовательность битов, которая следует правилам UTF-8.

Вот результаты в двоичном виде:

Initial Text(binary): 01001001 01001110 01000110 01001111 00100000 01000010 01001111 01000010 00100000 00110101 00110111 00110110 00110111 00110100
Encrypted Text(binary): 11101111 10111111 10111101 01001111 00100000 01011011 11101111 10111111 10111101 01100001 01011011 01100001 11101111 10111111 10111101 01101010 11101111 10111111 10111101 01101010 01110100
Decrypted Text(binary): 11101111 10111111 10111101 11101111 10111111 10111101 11101111 10111111 10111101 01001110 01000110 01001111 11101111 10111111 10111101 11101111 10111111 10111101 11101111 10111111 10111101 01000010 01001111 01000010 11101111 10111111 10111101 11101111 10111111 10111101 11101111 10111111 10111101 00110111 11101111 10111111 10111101 11101111 10111111 10111101 11101111 10111111 10111101 00110111 00110100

Теперь я ясно вижу проблему или руду. Похоже, что UTF-8 добавляет больше байтов в строку. Однако я не уверен почему. Я имею в виду, что первоначальный текст имеет одинаковое количество байтов, так почему же эти байты добавляются после шифрования и еще больше добавляются после дешифрования?

Буду признателен за любую предоставленную помощь. Заранее спасибо!

1 ответ

Решение

Каждый раз, когда вы делаете String.getBytes()вы неявно используете кодировку по умолчанию вашей платформы для преобразования символов в байты. Если строка содержит символы, которые не могут быть представлены с использованием кодировки по умолчанию вашей платформы, вы теряете информацию. Поэтому используйте явную кодировку, поддерживающую каждый символ на земле, например UTF8: string.getBytes("UTF8"),

Точно так же, когда вы делаете new String(bytes), вы используете кодировку по умолчанию вашей платформы для преобразования байтов в символы. Если байты на самом деле представляют собой текст, закодированный с использованием другой кодировки, или не являются символами вообще, а являются исключительно двоичной информацией, вы также потеряете информацию.

Шифрование - это бинарная операция. Он принимает байты и возвращает другие байты. Вы не можете слепо преобразовать байты в символы независимо от кодировки, потому что не все байты представляют допустимый символ. Если вы хотите преобразовать двоичную информацию (например, зашифрованный текст) в строку, используйте кодировку Hex или Base64.

Итак, процесс шифрования должен быть:

String clearText = ...:
byte[] clearTextAsBytes = clearText.getBytes("UTF8");
byte[] encryptedBinary = encrypt(clearTextAsBytes);
String encryptedBinaryAsPrintableChars = toBase64(encryptedBinary);

И процесс расшифровки должен быть симметричным:

String encryptedBinaryAsPrintableChars = ...;
byte[] encryptedBinary  = fromBase64(encryptedBinaryAsPrintableChars);
byte[] decryptedTextAsBytes = decrypt(encryptedBinary);
String decryptedText = new String(decryptedTextAsBytes, "UTF8");
Другие вопросы по тегам