我正在用Java编写一个流密码程序,该程序应该从shell中获取三个参数:一个带键的文件、一个用于输入的文件和一个用于输出的文件。然后密钥应该用作种子,该种子应该产生伪随机数;XOR:ed";输入文件中的明文。
我已经设法编写了用于读取文件的代码,但我不知道应该如何编写用于将密钥作为种子的代码,从而生成如上所述的伪随机数。有人能帮我吗?
public static void main(String[] args) throws IOException {
File key = null;
File input = null;
File output = null;
if (0 < args.length) {
key = new File(args[0])
input = new File(args[1]);
output = new File(args[2]);
}
//more stuff
//a function that takes the seed from the key file and should generate a pseudo-random number
int prng (long seed) {
Random random = new Random ();
int bound = 256;
int number = random.nextInt(bound);
return number;
}
赋值所描述的伪随机并不意味着您需要使用随机数生成器。流密码创建的密钥流是伪随机的(对对手来说(,因为它是由他们不知道的密钥生成的。因此,您不应该使用Random
或SecureRandom
或类似的内容。相反,您应该使用Cipher
。
基本上有两种方法可以实现CTR模式。首先,您可以创建一个16字节的唯一值流,并在ECB模式下使用AES对其进行加密(或者直接使用块密码,但这在Java中不可用(。然后得到16字节的密钥流作为回报,您可以缓冲这些密钥流并使用它们与明文进行异或。
你也可以作弊并使用AES/CTR/NoPadding
。然后,为了获得密钥流,您使用全部设置为零的字节进行更新。因为与零的XOR是身份函数,所以您将得到密钥流。这可以反过来与实际的明文进行异或以获得密文。由于这是为了练习,如果您实现前面的方法,您可能会学到更多。
使用java.util.Random
需要一个(伪(随机字节流。首先从用户那里读取种子/密钥,并使用它初始化Random类的实例。
long seedKey = getUserInput();
Random myRandom = new Random(seedKey);
只在代码开始时执行一次。
接下来,您需要处理您的输入。如果您对使用流感到满意,那么可以使用Random.ints()
或Random.longs()
来生成随机密钥流。或者,将输入文件分解为块,并使用Random.bytes(myAry)
获得足够的字节,以便与您正在使用的任何大小的块进行XOR。
除非您使用的是单字节块,否则您将需要处理输入末尾剩下的任何部分块。
XOR的输出将是原始字节,而不是文本。如果您需要文本输出,那么使用java.util.Base64
转换为Base64,这样您就可以获得可打印的内容,而原始加密字节则不是。