Расшифровка xOr заменяет правильную букву неправильной буквой во всем текстовом файле - PullRequest
0 голосов
/ 25 января 2019

Java: я шифрую и дешифрую текстовый файл, используя клавишу любых двух символов ASCII на клавиатуре.У меня они работают правильно, за исключением случаев, когда я зашифровал файл в строку для расшифровки.Он заменяет определенную букву другой неправильной буквой, но не все правильные буквы заменяются.Например, некоторые т заменяются на s.Я также видел, как некоторые b заменяются на e, когда я использую другой ключ.

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

public static String readFileToString(string filePath) {
    StringBuilder builder = new StringBuilder();
    try (Stream<String> stream = Files.get(filePath), StandardCharsets.UTF_8)){
        stream.forEach(s->builder.append(s).append("\n");
    }
    catch(IOException e){
        e.printStackTrace();
    }
    return builder.toString();
}

public static void writeFile(String crypt) throws IOException {
    Scanner sc = new Scanner(System.in);
    System.out.println("New file name: ");
    String fileName = sc.nextLine();
    String writtenString = crypt;
    String userHome = System.getProperty("user.home");
    File textFile = new File(userHome, fileName + ".txt");
    BufferedWriter out = new BufferedWriter(new FileWriter(textFile));
    out.write(writtenString);
    out.close();

//Converts string and key into binary characters for 1-to-1 xOr to prevent any possible translation errors.
public static String crypt(String input, String key) throws UnsupportedEncodingException {
    if (input.length() % 2 == 1) {
        input = input + " ";
    }
    int n = input.length() / 2;
    key = new String(new char[n]).replace("\0", key);
    byte[] a = input.getBytes();
    byte[] c = key.getBytes();
    StringBuilder binaryBuilder = new StringBuilder();
    StringBuilder binaryKeyBuilder = new StringBuilder();
    //Creates a StringBuilder of bits using the file text
    for(byte b: a) {
        int value = b;
        for(int i = 0; i < 8; i++) {
            binaryBuilder.append((value & 128) == 0 ? 0 : 1);
            value <<= 1;
        }
        binaryBuilder.append(' ');
    }
    //Converts binary StringBuilder to String
    String binary = binaryBuilder.toString();
    //Creates a StringBuilder of bits using the provided key
    for(byte d: c) {
        int keyValue = d;
        for(int j = 0; j < 8; j++) {
            binaryKeyBuilder.append((keyValue & 128) == 0 ? 0 : 1);
            keyValue <<= 1;
        }
        binaryKeyBuilder.append(' ');
    }
    //Converts binaryKey StringBuilder to String
    String binaryKey = binaryKeyBuilder.toString();
    //Creates StringBuilder of bits using the provided key
    StringBuilder xOr = new StringBuilder();
    for(int q = 0; q < binary.length();q++) {
        xOr.append(binary.charAt(q) ^ binaryKey.charAt(q));
    }
    String xOrResult = xOr.toString();
    String cryptedString = "";
    char next;
    //Iterates through binary string to convert to ASCII characters 8 bits at a time.
    for(int k = 0; k <= xOrResult.length()-8; k+=9) {
        next = (char)Integer.parseInt(xOrResult.substring(k,k+8), 2);
        cryptedString += next;
    }
    return cryptedString;
}

Когда я использую ключ "ty"

"Четыре счета и семьлет назад наши отцы воспитали на этом "правильное выражение.Тем не менее, я получаю: «Четыре очка и семь лет назад наши фешнессы выступают на этом»

1 Ответ

0 голосов
/ 25 января 2019

Я бы использовал двоичный файл для зашифрованного текста. Это избавит вас от необходимости кодировать / декодировать UTF-8 некоторые необычные кодовые точки. Например - когда вы xor 't' и 't', вы получите символ с кодом 0.

Вы также можете получить неожиданные символы новой строки. Вы фактически заменяете их всех на '\n', но есть и другие опции - '\r' или даже два символа в последовательности "\r\n". Все они будут заменены на '\ n' в вашем коде и приведут к ошибкам после расшифровки.

Что здесь произошло:

Двоичный код ASCII (или UTF-8) для t равен 01110100, а для y это 01111001. Когда символ y из ключа встречается с символом t из текста, вы получаете 01110100 xor 01111001 = 00001101 = 0x0D = '\r'. Этот символ записывается в файл. Когда вы читаете этот файл построчно, этот '\r' пропускается как разделитель строк. Вы заменяете его на '\n'=00001010 в строке

stream.forEach(s->builder.append(s).append("\n");

При расшифровке этого текста мы получаем 00001010 (\n) xor 01111001 (y) = 01110011 (s).

...