在Java中使用CipherOutputStream,加密文件最终会损坏
我正在写一篇关于密码学及其成本的学士论文 其中一部分是从运行时间和资源成本方面比较不同的加密算法和密码模式。 为此,我编写了一个小工具,它应该分为四个步骤:在Java中使用CipherOutputStream,加密文件最终会损坏,java,encryption,aes,Java,Encryption,Aes,我正在写一篇关于密码学及其成本的学士论文 其中一部分是从运行时间和资源成本方面比较不同的加密算法和密码模式。 为此,我编写了一个小工具,它应该分为四个步骤: 读取输入文件 加密输入文件并将其写入新文件 读取并解密刚刚写入的加密文件 将解密文件的另一个副本写入文件系统 比较初始输入文件和解密文件,看它们是否相等 它只需要一个小的.txt输入文件就可以正常工作。但由于某些原因,它不适用于任何其他类型的文件。如果我把一个图像作为输入文件,前几个像素是好的,其余的都被破坏了。 据我所知,问题应该是在初始
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Date;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
public class AES_Cipher_Test {
public String pLocalRef = "E:\\Test.txt";
public String pLocalRefOutput = "E:\\Test-crypted.txt";
public String pLocalCopyOutput = "E:\\Test-Neu.txt";
public Key pKeyAES = null;
public int pBitKey = 128;
public Cipher pCipher;
public FileOutputStream pFos;
public FileInputStream pFis;
public CipherOutputStream pCos;
public CipherInputStream pCis;
public File pInputFile = new File(this.pLocalRef);
public File pOutputFile = new File(this.pLocalRefOutput);
public File pGeneratedFile = new File(this.pLocalCopyOutput);
public AES_Cipher_Test() {
crypt_decrypt_write_File();
}
public void crypt_decrypt_write_File() {
byte[] lLoadedFile = null;
byte[] lGeneratedFileByte = null;
try {
// generate new random AES Key
KeyGenerator lKeygen = KeyGenerator.getInstance("AES");
lKeygen.init(this.pBitKey);
this.pKeyAES = lKeygen.generateKey();
// read input File
this.pFis = new FileInputStream(this.pInputFile);
FileInputStream tempStream = new FileInputStream(this.pInputFile);
int count = 0;
while (tempStream.read() != -1){
count ++;
}
lLoadedFile = new byte[count]; // new byte[this.pFis.available()]
this.pFis.read(lLoadedFile);
System.err.println("lLoadedFile.legth " + lLoadedFile.length);
this.pFis.close();
//init Cipher with AES Encrypt Mode CFB8 oder CTR
this.pCipher = Cipher.getInstance("AES/CTR/PKCS5Padding");
this.pCipher.init(Cipher.ENCRYPT_MODE, this.pKeyAES);
// build cipher stream from FileOutputStream
this.pFos = new FileOutputStream(this.pOutputFile);
this.pCos = new CipherOutputStream(this.pFos, this.pCipher);
//write encrypted Data to stream
this.pCos.write(lLoadedFile);
this.pCos.close();
this.pFos.close();
// init Cipher for decrypt Mode
this.pCipher.init(Cipher.DECRYPT_MODE, this.pKeyAES, new IvParameterSpec(this.pCipher.getIV()));
// read just written localFile and decrypt
this.pFis = new FileInputStream(this.pOutputFile);
tempStream = new FileInputStream(this.pOutputFile);
count = 0;
while (tempStream.read() != -1){
count ++;
}
byte[] lBytes = new byte[count];// new byte[this.pFis.available()]
this.pCis = new CipherInputStream(this.pFis, this.pCipher);
int lBytesRead = this.pCis.read(lBytes);
while (lBytesRead > -1) {
lBytesRead = this.pCis.read(lBytes);
}
this.pCis.close();
this.pFis.close();
System.err.println("lBytes.length " + lBytes.length);
// write new not crypted File to see if procedure works
this.pFos = new FileOutputStream(this.pLocalCopyOutput);
this.pFos.write(lBytes);
this.pFos.close();
//compare Input File and Output File
this.pFis = new FileInputStream(this.pGeneratedFile);
tempStream = new FileInputStream(this.pGeneratedFile);
count = 0;
while (tempStream.read() != -1){
count ++;
}
lGeneratedFileByte = new byte[count]; // new byte[this.pFis.available()]
int i = this.pFis.read(lGeneratedFileByte);
this.pFis.close();
System.err.println("lGeneratedFileByte.length " + i);
System.err.println("Test if initial File and new File are identical = " + Arrays.equals(lGeneratedFileByte, lLoadedFile));
} catch (FileNotFoundException e) {
throw new RuntimeException("FILE_DOES_NOT_EXIST", e);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String args[]) {
System.err.println("Start AES_Cipher_Test");
long start = new Date().getTime();
new AES_Cipher_Test();
long runningTime = new Date().getTime() - start;
System.err.println("End AES_Cipher_Test");
System.err.println("Runtime: " + runningTime);
}
}
常见的一系列错误
- 未指定
来填充缓冲区。它只指定传输至少一个字节,否则返回-1表示流的结束。您必须循环:read()
while ((count = in.read(buffer)) > 0) { out.write(buffer, 0, count); }
而(!(lBytesRead
基本上是无意义的
显式地不是流中的总字节数,任何使用它来分配如此大小的缓冲区的方法都在Javadoc中显式地声明为不正确。同样,您必须循环,请参见上文。available()
的用法很少,这不是其中之一available(),
while(lBytesRead@StephenC)很抱歉这些符号,但我必须使用它们,公司标准…@jonny-真的吗?真是个糟糕的主意。