我们实现了chunked文件解密,其方式是在文件开头添加初始化向量,然后是加密数据。以下解密方法解密文件并写入:
private void decrypt_AES_CBC_PKCS7(final byte[] symKeyBytes, final FileInputStream inputStream, final FileOutputStream outputStream) throws Exception {
Security.addProvider(new BouncyCastleProvider());
// Read init vector
final byte[] iv = new byte[16];
inputStream.read(iv, 0, 16);
// Prepare for decryption
final SecretKeySpec secretKeySpec = new SecretKeySpec(symKeyBytes, "AES");
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", new BouncyCastleProvider());
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
// Decrypt chunk by chunk
int chunkLen = 0;
final byte[] buffer = new byte[CHUNK_SIZE_DECRTPY]; // CHUNK_SIZE_DECRTPY = 20 * 1024 * 1024;
while ((chunkLen = inputStream.read(buffer)) > 0) {
byte[] decrypted = cipher.doFinal(buffer, 0, chunkLen);
outputStream.write(decrypted, 0, decrypted.length);
}
// close streams
inputStream.close();
outputStream.close();
}
代码在早期的Android版本(L& M)中运行良好,但是当我们在带有Android N的Nexus 5X上尝试时,在生成的文件的开头插入了16个“垃圾”字节。这仅在仅由一个块组成的文件中发生,即,大小大于一个块的文件将被正确解密,并且不会添加额外的字节。有趣的是,当附加Android Studio调试器运行代码时,在读取IV和读取输入流之间有一个断点,解密工作正常,输出文件中不会出现额外的字节。
示例加密文件(IV作为前16个字节可见,即第一行):
示例解密文件,前16个字节仅在Android N中添加:
欢迎所有建议!
答案 0 :(得分:0)
根据@martijno的建议,我检查了inputStream.read(iv, 0, 16)
的结果,结果发现它的第一次调用在Android N中返回-1。所以,我修改了读取IV的代码部分:
final byte[] iv = new byte[16];
int result;
int numTries = 0;
int MAX_NUM_TRIES = 2;
do {
result = inputStream.read(iv, 0, 16);
++numTries;
} while (result == -1 && numTries < MAX_NUM_TRIES);
if (result == -1) {
throw new Exception("Failed to read IV from file!");
}
事实证明,两次尝试阅读IV已足够,我们将在更多Android N设备可用时进一步测试。