我有一些大的文件,我想要AES加密,然后发送线路或保存到磁盘。虽然在加密流看来是可能的,但似乎存在针对这样做的警告,相反,人们建议将文件分割成块,并使用GCM或crypto/nacl/secretbox。
由于真实性要求,数据流的处理更加困难。我们不能加密-然后MAC:从本质上说,我们通常不知道流的大小。我们不能在流完成后发送MAC,因为这通常是由被关闭的流所指示的。我们不能在飞行中解密一个流,因为我们必须看到整个密文才能检查MAC。试图保护流增加了问题的巨大复杂性,没有好的答案。解决方案是将流分解为离散的块,并将它们视为消息。
文件被分割成4 4KiB块。每个块每次被修改时都会得到一个新的随机128位IV。128位认证标签(GHASH)保护每个块不受修改.
如果大量数据被解密,则在验证身份验证标记之前,不总是能够缓冲所有解密的数据。将数据分割成小块解决了延迟身份验证检查的问题,但引入了新的验证检查。大块可以重新排序..。...because每个块都是单独加密的。因此,块的顺序必须以某种方式编码到块本身中,以便能够检测到任意数量的块的重新排列。
有实际密码学经验的人能为我指明正确的方向吗?
更新
在问完这个问题后,我意识到在不能将整个字节流放入内存(加密一个10 24文件)和字节流也是一个未知的长度之间有一个区别,这个长度可能会远远超过解码该流的需要(一个24小时的实时视频流)。
我最感兴趣的是大气泡,在开始需要解码之前,可以到达流的末端。换句话说,不需要同时将整个明文/密文加载到内存中的加密。
发布于 2018-03-29 01:48:46
正如您已经从您的研究中发现的那样,对于经过身份验证的大型文件加密,并没有很好的解决方案。
传统上有两种方法来处理这个问题:
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
}发布于 2018-03-29 15:48:22
加密后使用HMAC是一种有效的方法。然而,HMAC可能非常慢,特别是如果使用SHA-2 .你实际上也可以对GMAC做同样的事情,GCM的底层MAC。找到一个实现可能很棘手,但是GMAC已经超过了密文,所以如果您真的想要的话,可以单独执行它。还有其他方法,例如用于TLS1.2和1.3的Poly1305和AES。
对于GCM (或CCM、EAX或任何其他经过身份验证的密码),您需要验证块的顺序。您可以通过创建一个单独的文件加密密钥,然后使用当前输入( 12字节IV)来指示块的数量来实现这一点。这将解决IV的存储问题,并确保各块处于有序状态。您可以使用KDF生成文件加密密钥(如果您有唯一的方法来指示该文件),或者使用主密钥包装随机密钥。
https://stackoverflow.com/questions/49546567
复制相似问题