使用 Java 过滤流通过 XOR 加密字符串

Encrypting a string with XOR using Java filter streams

我正在尝试使用伪随机数通过 XOR 加密文本,然后将加密文本写入文件。然后它再次读取文件,如果用户输入正确的密钥,它就会解密文本。 但是我得到的只是 ?????。我做错了什么?

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Random;
import java.util.Scanner;

public class MainTest
{
    public static void main(String[] args)
    {
        long seed = 754; // key
        Random random = new Random(seed);

        String message = "hello";

        try
        {
            OutputStream os = new FileOutputStream("test.txt");
            OutputStream bos = new BufferedOutputStream(os);
            EncryptOutputStream eos = new EncryptOutputStream(bos);

            for(int i = 0; i < message.length(); i++)
            {
                int z = random.nextInt();
                eos.write(message.charAt(i), z);
            }

            eos.close();

            InputStream is = new FileInputStream("test.txt");
            InputStream bis = new BufferedInputStream(is);
            DecryptInputStream dis = new DecryptInputStream(bis);

            Scanner scanner = new Scanner(System.in);
            System.out.print("Enter key: ");
            long key = scanner.nextLong();
            scanner.close();

            random = new Random(key);

            int c;
            while((c = dis.read(random.nextInt())) != -1)
            {
                System.out.print((char)c);  
            }

            dis.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

public class DecryptInputStream extends FilterInputStream
{

    protected DecryptInputStream(InputStream in)
    {
        super(in);
    }

    public int read(int z) throws IOException
    {
        int c = super.read();
        if(c == -1) return -1;
        return c^z;
    }
}
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class EncryptOutputStream extends FilterOutputStream
{

    public EncryptOutputStream(OutputStream o)
    {
        super(o);
    }

    public void write(int c, int z) throws IOException
    {
        super.write(c^z);
    }

}

我没有 EncryptOutputStream 的代码,但您似乎正在为每个字符获取一个随机整数。这意味着用户必须以相同的顺序输入每个整数才能解密。对于第一个 运行,获取一个随机整数,对其进行加密,然后使用单个整数对其进行解密。之后你可以变得更漂亮。

解密时,异或后需要屏蔽掉高位

public int read(int z) throws IOException
{
  int c = super.read();
  if(c == -1) return -1;
  return (c^z) & 0xFF; /* Only use lowest 8 bits */
}

加密时,您生成的是 32 位 int。最高有效的 16 位包含密钥流的高位,而低 16 位包含密文。但是,只有最低 8 位写入输出文件,因为 OutputStream 写入字节。对于消息 "hello," 这恰好没问题,因为所有这些字符无论如何都以最低 7 位编码。

然而,当您解密时,您再次创建了一个 32 位 int,其中高 24 位填充了密钥流中的位。当您转换为 char 时,第 31-16 位被丢弃,但第 15-8 位被垃圾填充,最低位 0-8 应包含原始字符。因为 char 的高位是垃圾,你得到乱码输出。