但是,接口cipher.AEAD的Seal方法有签名:
Seal(dst, nonce, plaintext, additionalData []byte) []byte
因此,对于非常大的文件,必须将所有文件内容读入内存,这是不可接受的.
一种可能的方法是在Seal和Open上实现Reader / Writer接口,但不应该通过AEAD的那些分组密码“模式”来解决?所以我想知道这是golang cipher lib的设计错误,还是我错过了GCM的重要内容?
最佳答案 AEAD不应该用于一次加密大量数据. API旨在阻止这种情况.
在单个操作中加密大量数据意味着a)要么所有数据都必须保存在内存中,要么b)API必须通过返回未经验证的明文来以流方式操作.
返回未经身份验证的数据是危险的,因为在互联网上找到人们建议像gpg这样的东西是not
hard -d your_archive.tgz.gpg | tar xz,因为gpg命令还提供了一个流媒体接口.
对于像AES-GCM这样的结构,它当然非常容易
如果应用程序没有,则随意操纵明文
在处理之前验证它.即使申请很小心
在真实性发生之前不要将明文“释放”到UI
建立后,流媒体设计暴露出更多的程序攻击面.
通过规范化大型密文并因此流式传输API,下一步
随之而来的协议更有可能在没有意识到的情况下使用它们
问题因而问题仍然存在.
优选地,明文输入将被分块为相当大的
部件(比如16KiB)和单独加密.块只需要
足够大以至于其他验证者的开销是
可以忽略不计.通过这种设计,可以逐步增加大量消息
处理时无需处理未经验证的明文,以及
AEAD API可以更安全. (更不用说更大的消息可以了
自AES-GCM以来处理的一个,对单个进行64GiB限制
纯文本.)
需要一些思考来确保块是正确的
顺序,即通过计数nonce,第一个块应该是第一个,即通过在零开始nonce,并且最后一个块应该是
最后,即通过附加一个特殊的空的终结器块
其他数据.但这并不难.
例如,请参阅miniLock中使用的分块.
即使有这样的设计,攻击者仍然可以造成这种情况
要被可检测地截断的消息.如果你想瞄准更高,一个
可以使用全有或全无变换,但这需要两个
传递输入并不总是可行的.