46 lines
1.4 KiB
Python
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
|