Go语言 为什么使用GCM的AES-256在密文大小上增加了16个字节?

gdx19jrr  于 2023-11-14  发布在  Go
关注(0)|答案(1)|浏览(218)

我使用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个字节呢?

f4t66c6m

f4t66c6m1#

AES-GCM提供机密性、完整性和认证,要提供后两个,需要一个认证标签。
总是计算16字节的标记大小,在您的情况下,它被追加。
更多详情;
1.**密文大小:**这始终等于明文大小,因为AES-GCM内部使用CTR模式进行加密,不需要填充。
1.**Nonce/IV大小:**GCM可以接受大(或小)的nonce,但建议使用12字节,因为它不需要额外的处理。12字节以外的任何值都使用GHASH处理;

if len(IV) = 96 then 
     J_0 = IV || 0^{31}1
 else 
     J_0=GHASH_H(IV||0^{s+64}||len(IV_64))

字符串
随机数通常被预先添加到消息中,这是密文大小的增加。
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)的输出

相关问题