使GoCM中的GCM / CBC密码可流式传输 [英] Making GCM/CBC ciphers streamable in golang

查看:196
本文介绍了使GoCM中的GCM / CBC密码可流式传输的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The GCM and CBC AES ciphers in Go can't be used along side with StreamWriter or StreamReader, which forces me to allocate the entire file into memory. Obviously, this is not ideal with large files.

我当时正在考虑通过将一些固定大小的块分配到内存中并将它们提供给GCM或CBC来使它们流式传输,但是我认为这可能不是一个好主意,因为一定有某种理由设计这种方式。

I was thinking of making them streamable, by allocation some fixed size of blocks into memory, and feeding them to GCM or CBC, but I'm assuming that is probably a bad idea, since there must be a reason they've been designed this way.

有人可以解释为什么这些操作模式可以

Can someone explain why these operation modes can't be used without allocating the entire files into memory?

推荐答案

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

Simple answer - that's how they designed the API.

CBC和GCM是非常不同的模式。 GCM是AEAD模式(具有关联数据的经过身份验证的加密)。您实际上需要身份验证吗?如果不是这样,则对于大文件,CBC非常适合。您也可以使用CTR或OFB,但它们是流模式,并且在选择IV时非常严格。

CBC and GCM are very different modes. GCM is AEAD mode (Authenticated Encryption with Associated Data). Do you actually need authentication? If not, for large files CBC is a good fit. You could also use CTR or OFB but they're streaming modes and are very strict about choosing an IV.

在实施任何内容之前,我建议您先阅读这些模式。您至少必须了解它们所需的参数,用于什么目的以及应如何生成它们。

Before implementing anything I suggest you read about these modes. You have to at least understand, which parameters they need, for what purpose and how they should be generated.

BlockMode 接口非常适合加密大型文件。您只需要逐块加密。 CBC需要填充,但是Go没有实现。至少我看不到。您必须以某种方式处理该问题。

BlockMode interface is a good fit for encrypting large files. You just need to encrypt block by block. CBC requires padding, but Go doesn't have the implementation. At least, I don't see one. You will have to deal with that somehow.

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

GCM uses AEAD interface, which only allows you to encrypt and decrypt a whole message. There is absolutely no reason why it should be implemented like that. GCM is a streaming mode, it's actually a good fit for streaming encryption. The only problem is authentication. GCM produces a tag at the end, which acts like a MAC. To make use of that tag you can't just encrypt an endless stream of data. You have to split it into chunks and authenticate them separately. Or do something else but at some point you have to read that tag and verify it, otherwise there's no point in using GCM.

某些库(包括Go)的作用是他们在加密时在末尾隐式地添加该标签,并在解密时读取并验证它。我个人认为这是一个非常糟糕的设计。标签应作为一个单独的实体提供,您不能仅仅假设它总是在结尾。这并不是Go实施中唯一的问题之一。
对不起,那家伙。最近,我处理了一个特别糟糕的实现。

What some libraries do, including Go, is they append that tag at the end implicitly on encryption and read and verify it on decryption. Personally, I think that's a very bad design. Tag should be available as a separate entity, you can't just assume that it will always be at the end. And that's not the only one of the problems in Go implementation. Sorry for that rant. Recently I've dealt with a particulary bad implementation.

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

As a solution I suggest you split your stream into chunks and encrypt them separately with a unique nonce (that's very important). Each chunk will have a tag at the end, which you should verify. That way you can make use of GCM authentication. Yes, it's kind of ugly but Go doesn't give you access to inner methods, so that you could make your own encryption API.

或者,您可以找到其他实现。甚至一个C库。我可以建议mbedtls。对我来说,这是我在API方面遇到的最好的实现。

As an alternative you could find a different implementation. Maybe even a C library. I can suggest mbedtls. For me, it's the best implementation I came across in terms of API.

这篇关于使GoCM中的GCM / CBC密码可流式传输的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆