在一个大块中加密 returns 整个文件

Cipher returns entire file in one large block

我们在 Android 应用程序中使用 CipherCipherInputStream 来解密从服务器下载的文件。

出于某种原因,所有对 Cipher.update return 的调用都是一个空块,而对 Cipher.doFinal return 的整个文件的调用都在一个块中。

这会导致大文件出现 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);
  1. 为什么会这样?
  2. 这是可以在客户端解决的问题吗?

注意:我目前无法访问服务器代码。当我拥有时,我也会 post 它。 注 2:这发生在 Android API 25.0.1

好问题!这是因为您使用的是 GCM 模式。在从服务器接收到所有数据之前无法检查身份验证标签,因此 Java 自动缓冲此数据,检查它,然后在检查完标签后为您提供最终数据。

GCM 模式非常适合相对较小的消息或文件,但不应该使用 GCM 模式加密大文件。

您可能更喜欢将 CBC 模式与 HMAC 结合使用,将文件流式传输到磁盘,验证 HMAC,然后然后 解密。它更迂回,但避免了您当前遇到的问题。