使 GCM/CBC 密码在 golang 中流式传输

Gre*_*ano 3 encryption aes go

Go 中的 GCM 和 CBC AES 密码不能与 StreamWriter 或 StreamReader 一起使用,这迫使我将整个文件分配到内存中。显然,这对于大文件来说并不理想。

我正在考虑通过将一些固定大小的块分配到内存中,并将它们提供给 GCM 或 CBC,使它们可流式传输,但我认为这可能是一个坏主意,因为必须有一个原因来设计它们道路。

有人可以解释为什么不将整个文件分配到内存就不能使用这些操作模式吗?

cre*_*ker 6

简单的答案 - 这就是他们设计 API 的方式。

CBC 和 GCM 是非常不同的模式。GCM 是 AEAD 模式(Authenticated Encryption with Associated Data)。你真的需要身份验证吗?如果没有,对于大文件,CBC 是一个很好的选择。您也可以使用 CTR 或 OFB,但它们是流模式,并且对选择 IV 非常严格。

在实施任何事情之前,我建议您阅读有关这些模式的信息。您至少必须了解它们需要哪些参数、用于什么目的以及它们应该如何生成。

加拿大广播公司

BlockMode界面非常适合加密大文件。您只需要逐块加密。CBC 需要填充,但 Go 没有实现。至少,我没有看到一个。你将不得不以某种方式处理它。

GCM

GCM 使用AEAD接口,它只允许您加密和解密整个消息。绝对没有理由应该这样实施。GCM 是一种流式模式,它实际上非常适合流式加密。唯一的问题是身份验证。GCM 在末尾生成一个标签,其作用类似于 MAC。要使用该标签,您不能仅仅加密无休止的数据流。您必须将其拆分为多个块并分别进行身份验证。或者做其他事情,但在某些时候您必须阅读该标签并进行验证,否则使用 GCM 毫无意义。

包括 Go 在内的一些库所做的是在加密的末尾隐式附加该标签,并在解密时读取和验证它。就个人而言,我认为这是一个非常糟糕的设计。标签应该作为一个单独的实体可用,你不能假设它总是在最后。这并不是 Go 实现中唯一的问题之一。对不起,我的咆哮。最近我处理了一个特别糟糕的实现。

作为解决方案,我建议您将流拆分为多个块,并使用唯一的随机数单独加密它们(这非常重要)。每个块的末尾都有一个标签,您应该对其进行验证。这样您就可以使用 GCM 身份验证。是的,这有点难看,但是 Go 不允许您访问内部方法,因此您可以创建自己的加密 API。

作为替代方案,您可以找到不同的实现。甚至可能是一个 C 库。我可以建议mbedtls。对我来说,这是我在 API 方面遇到的最好的实现。

  • 我需要 GCM 流。 (2认同)