Glossary

AES-GCM

AES-GCM is an authenticated encryption mode that encrypts with AES in counter mode and adds a tag, usually 16 bytes, proving the ciphertext and associated data are unchanged. GCM stands for Galois/Counter Mode and is defined in NIST SP 800-38D. RFC 8446 says a TLS 1.3 application must implement TLS_AES_128_GCM_SHA256 unless a profile says otherwise, so it is the default for web traffic.

How it works

GCM combines two parts that share one AES key. The first is counter mode, which encrypts a counter sequence and XORs it with the plaintext. The second is GHASH, a keyed function over the associated data and ciphertext. The tag is the GHASH result XORed with an AES encryption of the first counter block.

The inputs and sizes are:

  • Key: 128, 192 or 256 bits, matching AES-128, AES-192 and AES-256.
  • IV (nonce): NIST recommends exactly 96 bits (12 bytes). With a 96-bit IV the initial counter block is the IV followed by the 32-bit value 1.
  • Associated data (AAD): optional data that is authenticated but not encrypted, such as a record header.
  • Tag: 128 bits normally. NIST also lists 120, 112, 104 and 96 bits, and allows 64 or 32 only for certain applications.
  • Maximum plaintext: len(P) is at most 2^39 - 256 bits, a little under 64 GiB per message.

Decryption recomputes the tag first and rejects the message if it does not match. Libraries return the tag appended to the ciphertext, so the output is the plaintext length plus 16 bytes.

The example uses Python's cryptography package with a 128-bit key, an all-zero IV (only for a repeatable demo) and the associated data hdr. A Node.js run of the same inputs gave identical bytes.

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.exceptions import InvalidTag
key = bytes(range(16)); iv = bytes(12)
g = AESGCM(key)
out = g.encrypt(iv, b"hello", b"hdr")
print(len(out), out.hex())
print("ct", out[:5].hex(), "tag", out[5:].hex())
bad = bytearray(out); bad[0] ^= 1
try:
    g.decrypt(iv, bytes(bad), b"hdr")
except InvalidTag as e:
    print("InvalidTag", repr(str(e)))
21 21b3eb3ff680ba59a0ce79e52695c7f780b98426c2
ct 21b3eb3ff6 tag 80ba59a0ce79e52695c7f780b98426c2
InvalidTag ''

How long should an AES-GCM IV be?

An AES-GCM IV should be 96 bits, which is 12 bytes. NIST SP 800-38D recommends restricting implementations to that length for interoperability and speed. Other lengths work in most libraries, but GCM then has to hash the IV into a counter block, so NIST recommends 96 bits for interoperability and efficiency.

Can I reuse an AES-GCM nonce?

No. Reusing a key and IV pair leaks the XOR of the plaintexts, and NIST warns that a repeated IV makes forgery attacks possible. Two messages encrypted with the same key and IV, attack at dawn and retreat at six, produced the XOR 13110013060a5441155444121e16, which is the XOR of the plaintexts. When IVs are random, NIST requires the total number of encryptions under one key to stay at or below 2^32.

Common pitfalls

  • Reusing a key and IV: it breaks both confidentiality and authentication. Use a counter, or random IVs with a rotation before 2^32 messages.
  • Releasing plaintext before checking the tag: streaming decryption can hand back unverified bytes. Do not use the data until the tag verification succeeds.
  • Truncating the tag to 32 or 64 bits: NIST says GCM is not well-suited to short tags or very long messages. Keep 16 bytes.
  • Dropping the AAD on one side: the tag covers the AAD, so a missing or different header makes decryption fail with an empty InvalidTag error.
  • Using the password directly as the key: AES-GCM needs 16, 24 or 32 random bytes. Python raised "AESGCM key must be 128, 192, or 256 bits." for a 20-byte value. Derive keys with PBKDF2 or HKDF.

Related terms

  • AES — the block cipher underneath GCM.
  • GHASH — the polynomial hash that produces the authentication part of the tag.
  • AES-CTR — the encryption half of GCM without any authentication.
  • TLS — uses AES-GCM for record encryption.
  • HKDF — derives the keys that GCM consumes.
  • ChaCha20 — the common authenticated alternative on hardware without AES instructions.

See also