我有一些大文件,我想在发送电线或保存到磁盘之前加密AES。虽然似乎可以加密流,但似乎有警告反对这样做,而是建议人们建议将文件分配到块中,并使用GCM或Crypto/NACL/Secretbox。
由于真实性要求,处理数据流更加困难。我们不能加密到麦克风:从本质上讲,我们通常不知道流的大小。流完成后我们无法发送Mac,因为通常通过关闭流来表示。我们不能即时解密流,因为我们必须查看整个密文才能检查Mac。试图保护流可以为问题带来巨大的复杂性,没有好的答案。解决方案是将流分解成离散的块,并将其视为消息。
- https://leanpub.com/gocrypto/read
文件分为4KIB块。每个块每次修改时都会获得新的随机128位IV。128位身份验证标签(GHASH(可保护每个块免受修改。
- https://nuetzlich.net/gocryptfs/forward_mode_crypto/
如果大量数据被解密,则直到验证身份验证标签之前,并非总是可以缓冲所有解密数据。将数据分成小块可以解决递延身份验证检查的问题,但引入了新的。可以重新排序这些块……因为每个块都是分开加密的。因此,必须将块的顺序以某种方式编码到块本身中,以便能够检测到任何数量的块。
- https://github.com/minio/sio
任何具有实际密码学的人都可以将我指向正确的方向吗?
更新
我在问这个问题后意识到,根本无法将整个字节流安装到内存(加密10GB文件(和字节流也是一个未知的长度之间,这是有区别的可能会持续很长时间来解码流的需求(一个24小时的实时视频流(。
我对大型斑点很感兴趣,在开始,在需要解码开始之前,可以到达流的末端。换句话说,加密不需要整个明文/密文同时加载到内存中。
正如您已经从研究中发现的那样,对于 agen验证加密的优雅解决方案。
传统上有两种方法可以解决这个问题:
-
将文件分成块,单独加密每个块,让每个块都有自己的身份验证标签。AES-GCM将是最佳使用模式。此方法导致文件大小与文件大小成比例。您还需要一个独特的nonce。您还需要一种方法来指示块从哪里开始/结束。
-
使用带有缓冲区的AES-CTR加密,在HMAC上调用
Hash.Write
,以将其用于加密数据的每个缓冲区。这样做的好处是,加密可以在一次通过中进行。不利的一面是,解密需要一个通过来验证HMAC,然后再通过另一个通过才能真正解密。这里的好处是,文件大小保持不变,加上IV和HMAC结果的约48个左右的字节。
既不是理想的,但是对于非常大的文件(〜2GB或更多(,第二个选项可能是首选的。
我使用以下第二种方法包括了GO中加密的示例。在这种情况下,最后48个字节是IV(16个字节(和HMAC的结果(32个字节(。请注意IV的Hmacing。
const BUFFER_SIZE int = 4096
const IV_SIZE int = 16
func encrypt(filePathIn, filePathOut string, keyAes, keyHmac []byte) error {
inFile, err := os.Open(filePathIn)
if err != nil { return err }
defer inFile.Close()
outFile, err := os.Create(filePathOut)
if err != nil { return err }
defer outFile.Close()
iv := make([]byte, IV_SIZE)
_, err = rand.Read(iv)
if err != nil { return err }
aes, err := aes.NewCipher(keyAes)
if err != nil { return err }
ctr := cipher.NewCTR(aes, iv)
hmac := hmac.New(sha256.New, keyHmac)
buf := make([]byte, BUFFER_SIZE)
for {
n, err := inFile.Read(buf)
if err != nil && err != io.EOF { return err }
outBuf := make([]byte, n)
ctr.XORKeyStream(outBuf, buf[:n])
hmac.Write(outBuf)
outFile.Write(outBuf)
if err == io.EOF { break }
}
outFile.Write(iv)
hmac.Write(iv)
outFile.Write(hmac.Sum(nil))
return nil
}
加密后使用HMAC是一种有效的方法。但是,HMAC可能非常慢,尤其是在使用SHA-2的情况下。实际上,您可以使用GMAC(GCM的基础Mac(做同样的事情。找到实现可能很棘手,但是GMAC超过了Ciphertext,因此,如果您真的需要,您可以单独执行它。还有其他方法,例如poly1305,其AE与TLS 1.2和1.3一起使用。
。对于GCM(或CCM或EAX或任何其他身份验证的密码(,您需要对块的顺序进行身份验证。您可以通过创建一个单独的文件加密密钥,然后使用NONCE输入(12个字节IV(来执行此操作,以指示块的数量。这将解决IV 和的存储,请确保块井井有条。您可以使用KDF生成文件加密密钥(如果您有指示文件的唯一方法(或通过将随机密钥包装到主密钥中。