为什么带有 GCM 的 AES-256 会在密文大小上增加 16 个字节?

Why AES-256 with GCM adds 16 bytes to the ciphertext size?

我正在使用 Golang 的加密包,crypto/aes 具体而言,使用 32 字节密钥(因此,AES-256)和 GCM 方法(Galois/Counter 模式)。
我从一个文件中读取了多个 16384 字节的数据块,并生成了一个密码块、一个 GCM 方法和一个 12 字节的随机数。
然后,我将随机数添加到密文中,以便在解密时将它们拆分,以访问随机数(因为已知 12 字节的大小)。

预计生成的密文为16384 + 12 bytes = 16396;但是,在实际加密时,我得到 16412 字节的大小,因此添加了 16 个字节。在我解密每个块后,我得到了 16384 的“正常”大小。

这是一个快速示例。

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.
    */
}

好像不是padding的原因(也是因为GCM没有使用padding)

那么,为什么 AES 会在我的密文中添加 16 个字节?

AES-GCM 提供机密性、完整性和身份验证。要提供最后两个,需要一个身份验证标签。

始终会计算 16 字节的标记大小,并且在您的情况下会附加它。


更多详情;

  1. 密文大小:这始终等于明文大小,因为 AES-GCM 内部使用 CTR 模式进行加密,不需要填充。

  2. Nonce/IV size: 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))
    

    Nonce 通常添加到消息前,这是密文大小的增加。

  3. 标签大小: GCM 总是输出 16 字节的标签大小。可以 trim 但是,它会降低对伪造的安全性。

    标签通常附加在密文中。

    遵守NIST Special Publication 800-38D (page 8)

    The bit length of the tag, denoted t, is a security parameter, as discussed in Appendix B. In general, t may be any one of the following five values: 128, 120, 112, 104, or 96. For certain applications, t may be 64 or 32; guidance for the use of these two tag lengths, including requirements on the length of the input data and the lifetime of the key in these cases, is given in Appendix C.

因此您可能会看到类似 (Nonce|ciphertext|tag)

的输出