我使用CipherInputStream和CipherOutputStream来使用AES加密文件。
encrypt(...)
似乎工作正常,但我的decrypt(...)
函数只解密了我文件的前16个字节。
这是我的班级:
public class AESFiles {
private byte[] getKeyBytes(final byte[] key) throws Exception {
byte[] keyBytes = new byte[16];
System.arraycopy(key, 0, keyBytes, 0, Math.min(key.length, keyBytes.length));
return keyBytes;
}
public Cipher getCipherEncrypt(final byte[] key) throws Exception {
byte[] keyBytes = getKeyBytes(key);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
return cipher;
}
public Cipher getCipherDecrypt(byte[] key) throws Exception {
byte[] keyBytes = getKeyBytes(key);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
return cipher;
}
public void encrypt(File inputFile, File outputFile, byte[] key) throws Exception {
Cipher cipher = getCipherEncrypt(key);
FileOutputStream fos = null;
CipherOutputStream cos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(inputFile);
fos = new FileOutputStream(outputFile);
cos = new CipherOutputStream(fos, cipher);
byte[] data = new byte[1024];
int read = fis.read(data);
while (read != -1) {
cos.write(data, 0, read);
read = fis.read(data);
System.out.println(new String(data, "UTF-8").trim());
}
cos.flush();
} finally {
fos.close();
cos.close();
fis.close();
}
}
public void decrypt(File inputFile, File outputFile, byte[] key) throws Exception {
Cipher cipher = getCipherDecrypt(key);
FileOutputStream fos = null;
CipherInputStream cis = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(inputFile);
cis = new CipherInputStream(fis, cipher);
fos = new FileOutputStream(outputFile);
byte[] data = new byte[1024];
int read = cis.read(data);
while (read != -1) {
fos.write(data, 0, read);
read = cis.read(data);
System.out.println(new String(data, "UTF-8").trim());
}
} finally {
fos.close();
cis.close();
fis.close();
}
}
public static void main(String args[]) throws Exception {
byte[] key = "mykey".getBytes("UTF-8");
new AESFiles().encrypt(new File("C:\\Tests\\secure.txt"), new File("C:\\Tests\\secure.txt.aes"), key);
new AESFiles().decrypt(new File("C:\\Tests\\secure.txt.aes"), new File("C:\\Tests\\secure.txt.1"), key);
}
}
所以我的问题是,为什么decrypt
函数只读取前16个字节?
答案 0 :(得分:12)
这非常微妙。您的问题是,在<{1}} 之前,您正在关闭fos
。在您正在执行的cos
方法中:
encrypt(...)
关闭} finally {
fos.close();
cos.close();
fis.close();
}
下的FileOutputStream
,因此最终填充的加密输出块永远不会写入输出文件。如果您在CipherOutputStream
后关闭fos
,那么您的代码应该可以正常运行。
真的,你应该考虑做类似的事情:
cos
仅供参考: FileOutputStream fos = null;
CipherOutputStream cos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(inputFile);
fos = new FileOutputStream(outputFile);
cos = new CipherOutputStream(fos, cipher);
// once cos wraps the fos, you should set it to null
fos = null;
...
} finally {
if (cos != null) {
cos.close();
}
if (fos != null) {
fos.close();
}
if (fis != null) {
fis.close();
}
}
有一个很棒的org.apache.commons.io.IOUtils
方法可以处理closeQuietly(...)
次检查并为您捕获例外情况。