Secure cryptographic implementations.
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
def encrypt(plaintext: bytes, key: bytes) -> bytes:
"""Encrypt data with AES-GCM."""
# Generate random 96-bit nonce
nonce = os.urandom(12)
aesgcm = AESGCM(key)
ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data=None)
# Prepend nonce to ciphertext
return nonce + ciphertext
def decrypt(data: bytes, key: bytes) -> bytes:
"""Decrypt AES-GCM encrypted data."""
nonce = data[:12]
ciphertext = data[12:]
aesgcm = AESGCM(key)
return aesgcm.decrypt(nonce, ciphertext, associated_data=None)
# Generate a secure key
key = AESGCM.generate_key(bit_length=256)
from cryptography.fernet import Fernet
# Generate key
key = Fernet.generate_key()
# Encrypt
f = Fernet(key)
token = f.encrypt(b"secret message")
# Decrypt
plaintext = f.decrypt(token)
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
import os
def derive_key(password: str, salt: bytes = None) -> tuple[bytes, bytes]:
"""Derive encryption key from password."""
if salt is None:
salt = os.urandom(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=600000, # OWASP 2023 recommendation
)
key = kdf.derive(password.encode())
return key, salt
from argon2.low_level import hash_secret_raw, Type
def derive_key_argon2(password: str, salt: bytes = None) -> tuple[bytes, bytes]:
"""Derive key using Argon2id."""
if salt is None:
salt = os.urandom(16)
key = hash_secret_raw(
secret=password.encode(),
salt=salt,
time_cost=3,
memory_cost=65536,
parallelism=4,
hash_len=32,
type=Type.ID,
)
return key, salt
import hashlib
def hash_data(data: bytes) -> str:
"""Hash data for integrity checking."""
return hashlib.sha256(data).hexdigest()
def verify_integrity(data: bytes, expected_hash: str) -> bool:
"""Verify data hasn't been modified."""
return hashlib.sha256(data).hexdigest() == expected_hash
import hmac
import hashlib
def create_signature(message: bytes, key: bytes) -> str:
"""Create HMAC signature."""
return hmac.new(key, message, hashlib.sha256).hexdigest()
def verify_signature(message: bytes, signature: str, key: bytes) -> bool:
"""Verify HMAC signature (timing-safe)."""
expected = hmac.new(key, message, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization
# Generate key pair
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096,
)
public_key = private_key.public_key()
def sign(message: bytes, private_key) -> bytes:
"""Sign message with RSA."""
return private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
def verify(message: bytes, signature: bytes, public_key) -> bool:
"""Verify RSA signature."""
try:
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
return True
except:
return False
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
# Generate keys
private_key = Ed25519PrivateKey.generate()
public_key = private_key.public_key()
# Sign
signature = private_key.sign(message)
# Verify
try:
public_key.verify(signature, message)
print("Valid signature")
except:
print("Invalid signature")
import secrets
import os
# Cryptographically secure random bytes
random_bytes = os.urandom(32)
# Secure token generation
token = secrets.token_hex(32) # 64 hex chars
token = secrets.token_urlsafe(32) # URL-safe base64
token = secrets.token_bytes(32) # Raw bytes
# Secure random integer
pin = secrets.randbelow(1000000) # 0-999999
# Secure random choice
selected = secrets.choice(options)
import os
# Load key from environment
key = os.environ.get('ENCRYPTION_KEY')
if not key:
raise RuntimeError("ENCRYPTION_KEY not set")
key_bytes = bytes.fromhex(key)
import boto3
kms = boto3.client('kms')
def encrypt_with_kms(plaintext: bytes, key_id: str) -> bytes:
"""Encrypt using AWS KMS."""
response = kms.encrypt(
KeyId=key_id,
Plaintext=plaintext,
)
return response['CiphertextBlob']
def decrypt_with_kms(ciphertext: bytes) -> bytes:
"""Decrypt using AWS KMS."""
response = kms.decrypt(CiphertextBlob=ciphertext)
return response['Plaintext']
# WRONG - ECB reveals patterns
cipher = Cipher(algorithms.AES(key), modes.ECB())
# CORRECT - Use GCM or CBC with HMAC
cipher = Cipher(algorithms.AES(key), modes.GCM(iv))
# WRONG - Static IV
iv = b'1234567890123456'
# CORRECT - Random IV each time
iv = os.urandom(16)
# WRONG - Custom encryption
def encrypt(data, key):
return bytes([b ^ key[i % len(key)] for i, b in enumerate(data)])
# CORRECT - Use established libraries
from cryptography.fernet import Fernet
# WRONG - Weak hash
import hashlib
hash = hashlib.md5(password.encode())
# CORRECT - Use bcrypt for passwords
import bcrypt
hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
| Purpose | Algorithm | Library |
|---|---|---|
| Password hashing | bcrypt, Argon2 | bcrypt, argon2-cffi |
| Symmetric encryption | AES-256-GCM | cryptography |
| Key derivation | PBKDF2, Argon2 | cryptography, argon2 |
| Data integrity | SHA-256 | hashlib |
| Message auth | HMAC-SHA256 | hmac |
| Digital signatures | Ed25519, RSA-PSS | cryptography |
| Random bytes | CSPRNG | secrets, os.urandom |