Android N中的AES解密行为已更改

时间:2016-12-01 13:36:11

标签: java android encryption cryptography

我们实现了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个字节可见,即第一行):

Example encrypted file

示例解密文件,前16个字节仅在Android N中添加:

Example decrypted file

欢迎所有建议!

1 个答案:

答案 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设备可用时进一步测试。