Source code for converge.extensions.crypto.symmetric

"""Symmetric encryption utilities using AES-256-GCM."""

import secrets

from cryptography.hazmat.primitives.ciphers.aead import AESGCM


[docs] def encrypt(plaintext: bytes, key: bytes, associated_data: bytes | None = None) -> bytes: """ Encrypt plaintext with AES-256-GCM. Args: plaintext: Data to encrypt. key: 32-byte encryption key. associated_data: Optional authenticated associated data (not encrypted). Returns: nonce (12 bytes) + ciphertext + tag (16 bytes), concatenated. """ if len(key) != 32: raise ValueError("Key must be 32 bytes for AES-256") aesgcm = AESGCM(key) nonce = secrets.token_bytes(12) ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data or b"") return nonce + ciphertext
[docs] def decrypt(ciphertext: bytes, key: bytes, associated_data: bytes | None = None) -> bytes: """ Decrypt AES-256-GCM ciphertext. Args: ciphertext: nonce (12 bytes) + encrypted data + tag (16 bytes). key: 32-byte decryption key. associated_data: Same as used for encryption, if any. Returns: Decrypted plaintext. """ if len(key) != 32: raise ValueError("Key must be 32 bytes for AES-256") if len(ciphertext) < 12 + 16: raise ValueError("Ciphertext too short") nonce = ciphertext[:12] actual_ct = ciphertext[12:] aesgcm = AESGCM(key) return aesgcm.decrypt(nonce, actual_ct, associated_data or b"")