【问题标题】:Android: CipherStream-API for AEAD Ciphers inacceptable slowAndroid:AEAD 密码的 CipherStream-API 速度不可接受
【发布时间】:2019-06-22 10:13:16
【问题描述】:

我们有一个 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 结合使用?

【问题讨论】:

  • 将文件分成几部分。问题出在身份验证标签计算上。
  • 谢谢。但是如果将文件拆分为多个部分,则可以更改这些部分,例如一个部分可以加倍或左移,或者可以更改部分的顺序。在我看来,这将违反数据完整性的目标。

标签: android cryptography google-cloud-messaging


【解决方案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
  • 在除第一个部分之外的每个部分加上前一部分的身份验证标记。

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

你也可以

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

【讨论】:

  • 不幸的是,一些库以这种方式实现,对于标签计算,尽管可以并行完成,但它们会执行第二次数据传递。
  • 另外,看看 Maarten 的 cmets here
  • 有研究过这个结构吗?是否可以将块号和之前的标签作为附加的认证数据而不是明文提供给 AEAD 原语?
  • @JamesKPolk 我没有这方面的信息。我已经为这个问题创建了一个解决方案。我会搜索一下。
  • @JamesKPolk 我已经和 Maarten 谈过了,简而言之,这是设计师的决定,让人们不要即插即用 CBC 模式来忽略标签计算。一般。然后可以对其进行编码以支持流模式下的并行计算。
猜你喜欢
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 2017-09-10
  • 2018-02-20
  • 2019-08-02
  • 2017-06-29
  • 1970-01-01
  • 2016-07-22
相关资源
最近更新 更多