在一个大块中加密 returns 整个文件
Cipher returns entire file in one large block
我们在 Android 应用程序中使用 Cipher
和 CipherInputStream
来解密从服务器下载的文件。
出于某种原因,所有对 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);
- 为什么会这样?
- 这是可以在客户端解决的问题吗?
注意:我目前无法访问服务器代码。当我拥有时,我也会 post 它。
注 2:这发生在 Android API 25.0.1
好问题!这是因为您使用的是 GCM 模式。在从服务器接收到所有数据之前无法检查身份验证标签,因此 Java 自动缓冲此数据,检查它,然后在检查完标签后为您提供最终数据。
GCM 模式非常适合相对较小的消息或文件,但不应该使用 GCM 模式加密大文件。
您可能更喜欢将 CBC 模式与 HMAC 结合使用,将文件流式传输到磁盘,验证 HMAC,然后然后 解密。它更迂回,但避免了您当前遇到的问题。
我们在 Android 应用程序中使用 Cipher
和 CipherInputStream
来解密从服务器下载的文件。
出于某种原因,所有对 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);
- 为什么会这样?
- 这是可以在客户端解决的问题吗?
注意:我目前无法访问服务器代码。当我拥有时,我也会 post 它。 注 2:这发生在 Android API 25.0.1
好问题!这是因为您使用的是 GCM 模式。在从服务器接收到所有数据之前无法检查身份验证标签,因此 Java 自动缓冲此数据,检查它,然后在检查完标签后为您提供最终数据。
GCM 模式非常适合相对较小的消息或文件,但不应该使用 GCM 模式加密大文件。
您可能更喜欢将 CBC 模式与 HMAC 结合使用,将文件流式传输到磁盘,验证 HMAC,然后然后 解密。它更迂回,但避免了您当前遇到的问题。