AES GCM encryption and decryption in Python
Encrypt and decrypt data with AES-256-GCM using the cryptography library, including nonce generation and authenticated roundtrip verification.
pip install cryptography
Python code
21 linesimport os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def aes_gcm_demo():
plaintext = b"confidential message"
key = AESGCM.generate_key(bit_length=256)
aesgcm = AESGCM(key)
nonce = os.urandom(12)
ciphertext = aesgcm.encrypt(nonce, plaintext, None)
decrypted = aesgcm.decrypt(nonce, ciphertext, None)
print(f"Original: {plaintext.decode()}")
print(f"Key (hex): {key.hex()}")
print(f"Nonce (hex): {nonce.hex()}")
print(f"Ciphertext (hex): {ciphertext.hex()}")
print(f"Decrypted: {decrypted.decode()}")
print(f"Roundtrip OK: {plaintext == decrypted}")
if __name__ == "__main__":
aes_gcm_demo()
Output
Original: confidential message
Key (hex): 6f5b3a0c4d8e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6
Nonce (hex): a1b2c3d4e5f60718293a4b5c
Ciphertext (hex): 7c9e2f4a5b6d8c0e1f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d
Decrypted: confidential message
Roundtrip OK: True
How it works
The AESGCM class provides an authenticated encryption scheme where the ciphertext includes a 16-byte authentication tag by default. The 12-byte nonce must be unique for every encryption operation with the same key to prevent catastrophic confidentiality failure. Using None as the AAD (associated data) keeps the example simple, but production code should pass relevant context like a record ID or user ID. The roundtrip check confirms that decrypt successfully verifies authenticity and restores the exact plaintext, so any tamper with the ciphertext or nonce raises an InvalidTag exception.
Common mistakes
- Reusing the same nonce with the same key, which breaks AES-GCM security guarantees
- Using a nonce shorter than 12 bytes, which reduces security strength
- Storing the key or nonce as strings instead of bytes before hex encoding
Variations
- Use `AESGCM.generate_key(bit_length=128)` for a lighter AES-128 key
- Pass associated data like `b"user:42"` as the third argument for context binding
Real-world use cases
- Encrypting sensitive API tokens or database fields at rest in a service backend.
- Securing webhook payloads transmitted between microservices over authenticated channels.
- Protecting session cookies or signed URLs in a distributed auth system.
Sponsored
More from Auth & security at scale
- ACME LetsEncrypt Mock Challenge Server in Python medium
- Build a Mock OIDC Userinfo Endpoint in Python with Flask easy
- ChaCha20-Poly1305 mock in Python medium
- ECDH key agreement in Python with cryptography medium
- Enforce TLS 1.2 Minimum in Python easy
- Fetch Secrets from a Mock Secrets Manager in Python easy
Keep learning
Related tutorials and quizzes for this topic.