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.

Medium Python 3.7+ Aug 9, 2026 Auth & security at scale 18 views 0 copies

Requires third-party packages — install first
pip install cryptography

Python code

21 lines
Python 3.7+
import 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

stdout
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

  1. Use `AESGCM.generate_key(bit_length=128)` for a lighter AES-128 key
  2. 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

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Auth & security at scale

Related tutorials and quizzes for this topic.