infrasynth-backend-kit/infrasynth/shared/crypto.py
2026-08-28 14:38:47 -05:00

46 lines
1.4 KiB
Python

from cryptography.fernet import Fernet, InvalidToken
def get_fernet() -> Fernet:
key = _resolve_crypto_key()
if not key:
raise ValueError("CRYPTO_KEY not configured. Set INFRASYNTH_SECURITY['CRYPTO_KEY'] or CRYPTO_KEY env var.")
return Fernet(key.encode() if isinstance(key, str) else key)
def _resolve_crypto_key() -> str | None:
from django.conf import settings
key = getattr(settings, "INFRASYNTH_SECURITY", {}).get("CRYPTO_KEY")
if not key:
import os
key = os.environ.get("CRYPTO_KEY")
return key
def encrypt(value: str) -> str:
f = get_fernet()
return f.encrypt(value.encode()).decode()
def decrypt(token: str) -> str:
f = get_fernet()
try:
return f.decrypt(token.encode()).decode()
except InvalidToken:
raise ValueError("Invalid Fernet token or corrupted data.")
def generate_key() -> str:
return Fernet.generate_key().decode()
def rotate_keys(old_key: str, new_key: str, tokens: list[str]) -> list[str]:
old_fernet = Fernet(old_key.encode() if isinstance(old_key, str) else old_key)
new_fernet = Fernet(new_key.encode() if isinstance(new_key, str) else new_key)
re_encrypted = []
for token in tokens:
plaintext = old_fernet.decrypt(token.encode()).decode()
re_encrypted.append(new_fernet.encrypt(plaintext.encode()).decode())
return re_encrypted