import base64 import hashlib from cryptography.fernet import Fernet, InvalidToken from app.config import settings def _derive_fernet_key(key: str) -> bytes: """Derive a URL-safe base64-encoded 32-byte Fernet key from any string.""" digest = hashlib.sha256(key.encode("utf-8")).digest() return base64.urlsafe_b64encode(digest) _fernet = Fernet(_derive_fernet_key(settings.secret_encryption_key)) def encrypt_value(plain_text: str) -> str: """Encrypt a plaintext string and return the ciphertext as a string.""" token = _fernet.encrypt(plain_text.encode("utf-8")) return token.decode("utf-8") def decrypt_value(cipher_text: str) -> str: """Decrypt a ciphertext string and return the plaintext.""" try: plain = _fernet.decrypt(cipher_text.encode("utf-8")) except InvalidToken as exc: raise RuntimeError("Invalid encryption token — secret cannot be decrypted") from exc return plain.decode("utf-8")