xOr解密将整个文本文件中的正确字母替换为错误字母

时间:2019-01-25 15:06:21

标签: java binary readfile xor writefile

Java:我正在使用键盘上任意两个ASCII字符的键来加密和解密文本文件。我让它们正常工作,但当我将加密文件读取为字符串进行解密时除外。它将某些特定的字母替换为其他不正确的字母,但并非所有正确的字母都被替换。例如,某些t被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 :(得分:2)

我将使用二进制文件来加密文本。这将使您不必处理UTF-8编码/解码某些异常的代码点。例如-当您对“ t”和“ t”进行异或运算时,您会得到代码为0的字符。

您还会获得意外的换行符。实际上,您全部用WebMvcConfigurationSupport替换了它们,但是还有其他选项-'\n',甚至是序列'\r'中的两个字符。所有这些都将在您的代码中替换为“ \ n”,并在解密后导致错误。

这里发生了什么:

"\r\n"的二进制ASCII(或UTF-8)代码为t,而01110100的二进制ASCII代码为y。当键中的字符01111001与文本中的字符y相遇时,您将得到t。该字符被写入文件。当您逐行读取该文件时,此01110100 xor 01111001 = 00001101 = 0x0D = '\r'被跳过作为行分隔符。您将其替换为'\r'

'\n'=00001010

解密该文本时,我们得到stream.forEach(s->builder.append(s).append("\n");