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

时间:2017-04-10 20:13:47

标签: java encryption inputstream outputstream xor

我正在尝试使用伪随机数使用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);
    }

}

2 个答案:

答案 0 :(得分:1)

解密时,需要在异或之后屏蔽高阶位。

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的高位是垃圾,所以输出会出现乱码。

答案 1 :(得分:0)

我没有EncryptOutputStream的代码,但看起来你得到的是每个字符的随机整数。这意味着用户必须以相同的顺序输入每个整数才能解密它。对于第一次运行,获取ONE random int,对其进行加密,然后使用单个整数对其进行解密。之后你会变得更加漂亮。