In Part 1, we explored what end-to-end encryption is and why it matters. We also covered the basics of symmetric and asymmetric encryption. Now, we’ll focus on symmetric encryption — specifically using the AES algorithm — and implement it safely and effectively in Python.
Symmetric encryption uses the same secret key to both encrypt and decrypt data. It is fast and efficient, making it perfect for encrypting large messages or files. However, secure key management and correct usage of cryptographic primitives are critical.
Page Contents
Why AES?
AES (Advanced Encryption Standard) is the industry standard symmetric cipher. It is secure, widely supported, and implemented in hardware to optimize speed. AES can work in different modes; for secure encryption you should prefer authenticated modes like GCM (Galois/Counter Mode).
Getting Started: Installing the Cryptography Library
pip install cryptography
This library provides a high-level interface to AES and many other cryptographic functions.
Encrypting and Decrypting with AES-GCM
Here’s a simple example demonstrating how to encrypt and decrypt a message using AES in GCM mode.
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
def encrypt_message(key: bytes, plaintext: bytes, associated_data: bytes = None):
# Generate a random 12-byte nonce (number used once)
nonce = os.urandom(12)
aesgcm = AESGCM(key)
# Encrypt the data, applying optional authenticated data
ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data)
return nonce, ciphertext
def decrypt_message(key: bytes, nonce: bytes, ciphertext: bytes, associated_data: bytes = None):
aesgcm = AESGCM(key)
plaintext = aesgcm.decrypt(nonce, ciphertext, associated_data)
return plaintext
# Generate a secure 256-bit (32 bytes) key — share this key securely!
key = AESGCM.generate_key(bit_length=256)
message = b"Hello, this is a secret message!"
aad = b"metadata-or-associated-data" # Optional but recommended for data integrity
nonce, encrypted = encrypt_message(key, message, aad)
print(f"Nonce: {nonce.hex()}")
print(f"Encrypted: {encrypted.hex()}")
decrypted = decrypt_message(key, nonce, encrypted, aad)
print(f"Decrypted: {decrypted.decode()}")
Explanation:
- Key: Should be a securely generated 32-byte random value.
- Nonce: A unique random number per encryption operation; never reuse the same nonce with the same key.
- Associated Data (AAD): Optional data you want to authenticate (e.g., headers). It is not encrypted but will trigger authentication failure if altered.
- AESGCM.encrypt(): Returns ciphertext concatenated with the authentication tag.
- AESGCM.decrypt(): Verifies the tag and decrypts.
Important Security Notes
- Never reuse nonces with the same key. This compromises security drastically.
- Store or transmit the nonce with the ciphertext (it’s not secret).
- Use a secure key exchange mechanism (asymmetric encryption) to share the AES key safely.
- Use authenticated encryption modes (e.g., GCM, ChaCha20-Poly1305) to ensure integrity and authenticity.
- Avoid ECB mode — it’s insecure and leaks patterns.
Encrypting Files Safely
Many use cases involve encrypting files rather than strings. Here is a simple way to encrypt and decrypt files with AES-GCM:
def encrypt_file(key: bytes, in_filename: str, out_filename: str):
nonce = os.urandom(12)
aesgcm = AESGCM(key)
with open(in_filename, 'rb') as f:
data = f.read()
encrypted_data = aesgcm.encrypt(nonce, data, None)
with open(out_filename, 'wb') as f:
# Write nonce + ciphertext
f.write(nonce + encrypted_data)
def decrypt_file(key: bytes, in_filename: str, out_filename: str):
aesgcm = AESGCM(key)
with open(in_filename, 'rb') as f:
nonce = f.read(12)
ciphertext = f.read()
decrypted_data = aesgcm.decrypt(nonce, ciphertext, None)
with open(out_filename, 'wb') as f:
f.write(decrypted_data)
# Usage example
key = AESGCM.generate_key(bit_length=256)
encrypt_file(key, 'secret.pdf', 'secret_encrypted.bin')
decrypt_file(key, 'secret_encrypted.bin', 'secret_decrypted.pdf')
Key Management: What You Need to Know
- Never hardcode keys in your source code.
- Store keys in secure vaults or environment variables.
- Use proper key exchange protocols (covered in Part 3).
- Rotate keys periodically for long-lived data.
Summary
- Symmetric encryption is the backbone of E2EE for fast, bulk data encryption.
- AES-GCM ensures both confidentiality and integrity.
- Secure key and nonce management is critical.
- Python’s
cryptographylibrary offers a clean, effective AES API.
What’s Next?
In Part 3, we will implement asymmetric encryption with RSA and elliptic curve cryptography. You’ll learn how to generate key pairs and encrypt messages securely for key exchange and digital signatures.
Try It Yourself
pip install cryptography
Copy the code snippets above, experiment with encrypting and decrypting messages or files, and observe what happens if you reuse a nonce or tamper with ciphertext.
Feel free to ask questions or share your experience in the comments!
Useful Links
| Resource | URL | Description |
|---|---|---|
| Cryptography Library Docs | https://cryptography.io/en/latest/ | Official documentation for the Python cryptography library. |
| AES-GCM Specification | https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf | NIST documentation on AES-GCM mode (standard reference). |
| PyNaCl Library | https://pynacl.readthedocs.io/en/latest/ | Python binding for the NaCl cryptography library. |
| PyCryptodome Library | https://pycryptodome.readthedocs.io/en/latest/ | Alternative Python crypto library with AES support. |
| OWASP Cryptographic Storage | https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html | Best practices for cryptographic storage from OWASP. |
| Python Official Documentation | https://docs.python.org/3/library/os.html | For generating cryptographically strong random numbers. |
More Links
- Learn more about the
cryptographylibrary - Explore the AES-GCM standard from NIST
- Try PyNaCl for easy-to-use modern cryptography in Python
- Check out PyCryptodome as an alternative crypto library
- Follow OWASP’s Cryptographic Storage Cheat Sheet for secure practices

