Go 中的 GCM 和 CBC AES 密码不能与 StreamWriter 或 StreamReader 一起使用,这迫使我将整个文件分配到内存中。显然,这对于大文件来说并不理想。
我正在考虑通过将一些固定大小的块分配到内存中并将它们提供给 GCM 或 CBC 来使它们可流式传输,但我认为这可能是一个坏主意,因为它们被设计成这样肯定是有原因的方式。
有人可以解释为什么在不将整个文件分配到内存中的情况下不能使用这些操作模式吗?
答案很简单——这就是他们设计 API 的方式。
CBC 和 GCM 是非常不同的模式。 GCM 是 AEAD 模式(带有关联数据的验证加密)。您真的需要身份验证吗?如果没有,对于大文件,CBC 是一个不错的选择。您也可以使用 CTR 或 OFB,但它们是流媒体模式,并且对 IV 的选择非常严格。
在实施任何操作之前,我建议您阅读有关这些模式的信息。您至少必须了解它们需要哪些参数、用于什么目的以及如何生成它们。
CBC
BlockMode
接口非常适合加密大文件。您只需要逐块加密即可。 CBC 需要填充,但 Go 没有实现。至少,我没有看到一个。你将不得不以某种方式处理这个问题。
GCM
气相色谱仪用途AEAD
接口,它只允许您加密和解密整个消息。绝对没有理由要这样实施。 GCM是一种流模式,它实际上非常适合流加密。唯一的问题是身份验证。 GCM 在末尾生成一个标签,其作用类似于 MAC。要利用该标签,您不能仅仅加密无尽的数据流。您必须将其分成多个块并分别对它们进行身份验证。或者做其他事情,但在某些时候您必须读取该标签并验证它,否则使用 GCM 就没有意义。
一些库(包括 Go)所做的就是在加密时隐式地在末尾附加该标签,并在解密时读取和验证它。就我个人而言,我认为这是一个非常糟糕的设计。标签应该作为单独的实体提供,您不能假设它始终位于末尾。这并不是 Go 实现中的唯一问题之一。
很抱歉那次咆哮。最近我遇到了一个特别糟糕的实现。
作为解决方案,我建议您将流分成块,并使用唯一的随机数单独加密它们(这非常重要)。每个块末尾都会有一个标签,您应该验证该标签。这样您就可以使用 GCM 身份验证。是的,这有点丑陋,但是 Go 不允许您访问内部方法,因此您可以创建自己的加密 API。
作为替代方案,您可以找到不同的实现。甚至可能是一个 C 库。我可以建议 mbedtls。对我来说,这是我在 API 方面遇到的最好的实现。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)