我正在使用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个字节? 最佳答案
这是非常微妙的。您的问题是您在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(...)
方法,该方法可以处理null
检查并为您捕获异常。