使用 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 的高位是垃圾,你得到乱码输出。
我正在尝试使用伪随机数通过 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 的高位是垃圾,你得到乱码输出。