Android:AEAD Ciphers的CipherStream-API速度慢

时间:2019-01-29 10:02:12

标签: android cryptography google-cloud-messaging

我们有一个android应用,可通过HTTP流对大型(最大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结合使用的解决方案?

1 个答案:

答案 0 :(得分:1)

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

假设您将文件分为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
  • 除第一个零件以外的每个零件都以上一个零件的身份验证标签作为前缀。

有了这些,您现在有了一个可以在解密后进行控制的链。您可以检测,添加,删除。订单由您控制,即使没有订单也可以发送。但是,您需要检查前缀。

您也可以

  • 添加零件尺寸,然后
  • 如果您担心重放攻击,也要增加加密时间。