我们在Android应用中使用Cipher
和CipherInputStream
来解密从服务器下载的文件。
由于某种原因,对Cipher.update
的所有调用都返回一个空块,对Cipher.doFinal
的调用将在一个块中返回整个文件。
这会导致大文件上的OOM。
这是我们用来初始化密码的代码:
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec key = new SecretKeySpec(keyData, "AES");
GCMParameterSpec nonce = new GCMParameterSpec(128, nonceData);
cipher.init(Cipher.DECRYPT_MODE, key, nonce);
注意:我目前无法访问服务器的代码。我有的时候也会发布。 注意2:这在Android API 25.0.1上发生
答案 0 :(得分:1)
好问题!这是因为您正在使用GCM模式。无法检查身份验证标记,直到从服务器收到所有数据,因此Java会自动缓冲此数据,检查数据,然后在检查标记后为您提供最终数据。
GCM模式非常适合相对较小的邮件大小或文件,但大文件不应使用GCM模式加密。
您可能更喜欢将CBC模式与HMAC一起使用,将文件流式传输到磁盘,验证HMAC并然后解密。它更加迂回,但避免了您目前所遇到的问题。