我们在 Android 应用程序中使用 Cipher
和 CipherInputStream
来解密从服务器下载的文件。
出于某种原因,所有对 Cipher.update
的调用都会返回一个空 block ,而对 Cipher.doFinal
的调用会在一个 block 中返回整个文件。
这会导致大文件 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
最佳答案
好问题!这是因为您使用的是 GCM 模式。在从服务器接收到所有数据之前,无法检查身份验证标记,因此 Java 会自动缓冲这些数据,对其进行检查,然后在检查完标记后为您提供最终数据。
GCM 模式非常适合相对较小的消息或文件,但不应使用 GCM 模式加密大文件。
您可能更喜欢将 CBC 模式与 HMAC 结合使用,将文件流式传输到磁盘,验证 HMAC,然后然后解密。它更迂回,但避免了您当前遇到的问题。
关于android - 密码在一个大块中返回整个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49970093/