我正在尝试使用伪随机数使用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);
}
}
答案 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,对其进行加密,然后使用单个整数对其进行解密。之后你会变得更加漂亮。