阅读和阅读问题在Java

时间:2016-05-16 18:28:07

标签: java encryption io

从Java中读取非常大的加密文件时,我使用以下代码:

FileInputStream in = new FileInputStream("file.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();

Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(saveLocation), "utf-8"));

int read;
byte buffer[] = new byte[16384];
byte getData[] = new byte[16384];

while((read = in.read(buffer)) != -1)
{

 baos.write(buffer, 0, read);

 Cipher cipher = Cipher.getInstance(symCipher);
 IvParameterSpec ivParameterSpec = new IvParameterSpec(initVecBytes);
 cipher.init(Cipher.DECRYPT_MODE, originalKey, ivParameterSpec);
 byte[] original = cipher.doFinal(baos.toByteArray());
 String s = new String(original);
 writer.append(s);
 baos.reset();
}

writer.close();

由于文件非常大(对于我来说太大而无法一次性加载到内存中)我将其读入一个小缓冲区,然后加密小字节数据,最后将它们写入文件。

然而,当我这样做时,一些数据看起来已损坏:

</AddressLine><_��SR����_�hEE</AddressLine></AddressLines><Postcode>

我使用的文件不是16k时,它运行正常,我似乎只是在新数组读取开始时获得少量损坏的数据,然后它就会#39 ; s再次没问题,直到下一个数组读取,依此类推。

任何人都知道为什么这不能正常工作?

2 个答案:

答案 0 :(得分:1)

  1. 摆脱ByteArrayOutputStreamWriter并将解密后的数组直接写入FileOutputStream
  2. 在加密和解密时对整个文件使用相同的Cipher,并将其初始化一次,而不是每次读取一次。
  3. 您可以使用CipherInputStream约五行代码完成所有这些操作。

答案 1 :(得分:1)

它无效,因为大多数密码都是有状态的。具体来说,在密码块链接模式中,明文必须与先前的密文块进行异或。但是每16k,你用IV反而对它进行异或。您无法在解密操作过程中重新初始化Cipher

以下是五行代码to which EJP alluded.

Cipher cipher = Cipher.getInstance(symCipher);
cipher.init(Cipher.DECRYPT_MODE, originalKey, new IvParameterSpec(initVecBytes));
try (InputStream in = Files.newInputStream(Paths.get("file.txt"))) {
  Files.copy(new CipherInputStream(in, cipher), Paths.get(saveLocation));
}