如何在 golang 中使用 AES256-GCM 加密文件?
How to encrypt files with AES256-GCM in golang?
AES256-GCM 可以在 go 中实现为 https://gist.github.com/cannium/c167a19030f2a3c6adbb5a5174bea3ff
但是,接口 cipher.AEAD
的 Seal
方法具有签名:
Seal(dst, nonce, plaintext, additionalData []byte) []byte
所以对于非常大的文件,必须将文件内容全部读入内存,这是不可接受的。
一种可能的方法是在 Seal
和 Open
上实现 Reader
/Writer
接口,但这不应该由那些块密码解决 "modes" AEAD?所以我想知道这是否是 golang 密码库的设计错误,或者我错过了 GCM 的重要内容?
这不是设计错误。只是 API 在这方面不完整。
GCM 是一种流操作模式,因此能够在不停止流的情况下按需处理加密和解密。看来不能和之前的MAC状态重用同一个AEAD实例,所以不能直接用这个API进行GCM加密。
您可以在 crypto.NewCTR
和您自己的 GHASH 实现之上实现您自己的 GCM。
不应使用 AEAD 一次性加密大量数据。 API 旨在阻止这种情况。
在单个操作中加密大量数据意味着 a) 所有数据都必须保存在内存中或 b) API 必须通过返回未经身份验证的明文以流式传输方式运行。
返回未经身份验证的数据是危险的 不是
很难 在 Internet 上找到建议类似 gpg -d your_archive.tgz.gpg | tar xz
的人,因为 gpg 命令还提供了流接口。
使用 AES-GCM 这样的结构,当然很容易
如果应用程序不这样做,可以随意操作明文
在处理之前对其进行身份验证。即使应用程序很小心
在真实性得到验证之前,不要将 "release" 明文转为 UI
成立,流式设计暴露了更多的程序攻击面。
通过标准化大密文并因此流式传输 APIs,下一个
出现的协议更有可能在没有意识到的情况下使用它们
问题,因此问题仍然存在。
最好将纯文本输入分成相当大的块
部分(例如 16KiB)并单独加密。这些块只需要是
足够大,额外的认证器的开销是
微不足道。有了这样的设计,大消息可以递增
无需处理未经身份验证的明文即可处理,并且
AEAD APIs 可以更安全。 (更不用说更大的消息可以
由于 AES-GCM 处理,例如,单个文件有 64GiB 的限制
明文。)
需要一些想法来确保块在正确的位置
顺序,即通过计算随机数,第一个块应该是第一个,即从零开始随机数,最后一个块应该是
最后,即通过附加一个空的终止符块
附加数据。但这并不难。
例如,请参阅 miniLock 中使用的分块。
即使有这样的设计,攻击者仍然可以造成这种情况
消息被可检测地截断。如果你想瞄准更高的目标,
可以使用全有或全无变换,尽管这需要两个
传递输入并不总是可行的。
AES256-GCM 可以在 go 中实现为 https://gist.github.com/cannium/c167a19030f2a3c6adbb5a5174bea3ff
但是,接口 cipher.AEAD
的 Seal
方法具有签名:
Seal(dst, nonce, plaintext, additionalData []byte) []byte
所以对于非常大的文件,必须将文件内容全部读入内存,这是不可接受的。
一种可能的方法是在 Seal
和 Open
上实现 Reader
/Writer
接口,但这不应该由那些块密码解决 "modes" AEAD?所以我想知道这是否是 golang 密码库的设计错误,或者我错过了 GCM 的重要内容?
这不是设计错误。只是 API 在这方面不完整。
GCM 是一种流操作模式,因此能够在不停止流的情况下按需处理加密和解密。看来不能和之前的MAC状态重用同一个AEAD实例,所以不能直接用这个API进行GCM加密。
您可以在 crypto.NewCTR
和您自己的 GHASH 实现之上实现您自己的 GCM。
不应使用 AEAD 一次性加密大量数据。 API 旨在阻止这种情况。
在单个操作中加密大量数据意味着 a) 所有数据都必须保存在内存中或 b) API 必须通过返回未经身份验证的明文以流式传输方式运行。
返回未经身份验证的数据是危险的 不是
很难 在 Internet 上找到建议类似 gpg -d your_archive.tgz.gpg | tar xz
的人,因为 gpg 命令还提供了流接口。
使用 AES-GCM 这样的结构,当然很容易 如果应用程序不这样做,可以随意操作明文 在处理之前对其进行身份验证。即使应用程序很小心 在真实性得到验证之前,不要将 "release" 明文转为 UI 成立,流式设计暴露了更多的程序攻击面。
通过标准化大密文并因此流式传输 APIs,下一个 出现的协议更有可能在没有意识到的情况下使用它们 问题,因此问题仍然存在。
最好将纯文本输入分成相当大的块 部分(例如 16KiB)并单独加密。这些块只需要是 足够大,额外的认证器的开销是 微不足道。有了这样的设计,大消息可以递增 无需处理未经身份验证的明文即可处理,并且 AEAD APIs 可以更安全。 (更不用说更大的消息可以 由于 AES-GCM 处理,例如,单个文件有 64GiB 的限制 明文。)
需要一些想法来确保块在正确的位置 顺序,即通过计算随机数,第一个块应该是第一个,即从零开始随机数,最后一个块应该是 最后,即通过附加一个空的终止符块 附加数据。但这并不难。
例如,请参阅 miniLock 中使用的分块。
即使有这样的设计,攻击者仍然可以造成这种情况 消息被可检测地截断。如果你想瞄准更高的目标, 可以使用全有或全无变换,尽管这需要两个 传递输入并不总是可行的。