Android:AEAD 密码的 CipherStream-API 慢得无法接受

Android: CipherStream-API for AEAD Ciphers inacceptable slow

我们有一个 android 应用程序,可以通过 HTTP-Streams 解密和加密大型(最多 100MB)文件。

因此,我们正在使用 CipherInputStreamsCipherOutputStreams,这对 AES/CBC/PKCS7Padding 来说效果很好。我们最近切换到 AES/GCM/NoPadding。现在加密和解密对于大约 50MB 的文件来说是慢得不能接受的。

调试 android 源代码,揭示问题:https://android.googlesource.com/platform/libcore/+/master/ojluni/src/main/java/javax/crypto/CipherInputStream.java#112

此方法有字节缓冲区 "oBuffer",它被 重新分配 并增加了 512 位,直到它可以容纳整个消息(见行:https://android.googlesource.com/platform/libcore/+/master/ojluni/src/main/java/javax/crypto/CipherInputStream.java#121

我知道有关此方法的说明,其中指出在 AEAD 密码中必须缓冲整个消息。这是一个问题,因为我们不能将整个消息保存到内存缓冲区中。另一个问题是 oBuffer 不断被重新分配。

是否有将 GCM 与流媒体一起使用的解决方案API?

将文件拆分成多个部分并链接是适合您的解决方案。

假设您将文件分成 n 个部分。使用 AES-GCM 加密它们中的每一个并添加以下内容。加密前各部分前缀如下;

tag_0 = ''
for i from 1 to n
    ciphertextBlock_i, tag_i = AES-GCM( i:n || tag_i-1 || plaintextBlock_i)
  • 在每个零件前面加上零件号作为i:n
  • 在除第一个部分之外的每个部分前面加上前一部分的身份验证标记。

有了这些,你就有了一条解密后可以控制的链。可以检测、添加、删除。订单由您掌控,即使没有订单,您也可以发送。但是,您需要检查前缀。

你也可以

  • 添加零件尺寸,
  • 如果你害怕重放攻击,也加上加密时间。