我使用Golang的crypto包,特别是crypto/aes,有一个32字节的密钥(所以,AES-256)和GCM方法(伽罗瓦/计数器模式)。
我从一个文件中读取多个16384字节的块,并生成一个密码块,一个GCM方法和一个12字节的随机数。
然后,我将随机数前置到密文中,以便在解密时拆分它们,以访问随机数(因为12字节的大小是已知的)。
人们会期望生成的密文是16384 + 12 bytes = 16396;但是,在实际加密时,我得到的大小是16412 bytes,因此增加了16 bytes。
这里有一个快速的例子。
block, _ := aes.NewCipher([]byte("W9FLKnyv397R82kKuFpfp6y8usGRf49a"))
gcm, _ := cipher.NewGCM(block)
nonce = make([]byte, gcm.nonceSize()) // nonceSize is 12 bytes
_, _ = io.ReadFull(rand.Reader, nonce) // populate nonce with random data
for {
src := make([]byte, 1024 * 16) // let's hypotise this src is a chunk of a file, full of 1024 * 16 bytes, so 16384
encryptedBytes := gcm.Seal(nonce, nonce, src, nil) // this prepends the nonce to the src, thus adding 12 bytes in front of the encrypted string
/*
Now, encryptedBytes should be 16384 + 12 bytes long, but it is 16384 + 12 + 16.
If I want to decrypt a chunk of the encrypted bytes, I need to use the size of 16384 + 12 + 16 and this makes it unpractical.
*/
}
字符串
这似乎不是因为填充(也因为GCM不使用填充)。
那么,为什么AES会在我的密文中增加16个字节呢?
1条答案
按热度按时间f4t66c6m1#
AES-GCM提供机密性、完整性和认证,要提供后两个,需要一个认证标签。
总是计算16字节的标记大小,在您的情况下,它被追加。
更多详情;
1.**密文大小:**这始终等于明文大小,因为AES-GCM内部使用CTR模式进行加密,不需要填充。
1.**Nonce/IV大小:**GCM可以接受大(或小)的nonce,但建议使用12字节,因为它不需要额外的处理。12字节以外的任何值都使用GHASH处理;
字符串
随机数通常被预先添加到消息中,这是密文大小的增加。
1.**标签大小:**GCM始终输出16字节的标签大小,可以对其进行裁剪,但会降低针对foreign的安全性。
标记通常附加在密文之后。
为了符合NIST Special Publication 800-38D (page 8)
标记的位长度(表示为
t
)是安全参数,如附录B中所讨论的。通常,t
可以是以下五个值中的任何一个:128、120、112、104或96。对于某些应用,t
可以是64或32;附录C提供了使用这两种标签长度的指南,包括在这些情况下对输入数据长度和密钥寿命的要求。因此,您可能会看到类似
(Nonce|ciphertext|tag)
的输出