Files

47 lines
1.5 KiB
Python

from __future__ import annotations
from cryptography.fernet import Fernet, InvalidToken
from django.conf import settings
class AiKeyEncryptionError(RuntimeError):
"""Raised when AI provider key encryption/decryption cannot proceed."""
PREFIX = "fernet:"
def encrypt_api_key(raw_api_key: str) -> str:
api_key = str(raw_api_key or "").strip()
if not api_key:
raise AiKeyEncryptionError("AI api_key cannot be blank")
token = _fernet().encrypt(api_key.encode("utf-8")).decode("ascii")
return f"{PREFIX}{token}"
def decrypt_api_key(encrypted_api_key: str) -> str:
encrypted = str(encrypted_api_key or "")
if not encrypted:
return ""
if not encrypted.startswith(PREFIX):
raise AiKeyEncryptionError("AI api_key is not stored in encrypted form")
token = encrypted[len(PREFIX) :].encode("ascii")
try:
return _fernet().decrypt(token).decode("utf-8")
except InvalidToken as exc:
raise AiKeyEncryptionError("AI api_key cannot be decrypted") from exc
def mask_secret(encrypted_api_key: str) -> str:
return "********" if encrypted_api_key else ""
def _fernet() -> Fernet:
key = getattr(settings, "AI_KEY_ENCRYPTION_KEY", "")
if not key:
raise AiKeyEncryptionError("AI_KEY_ENCRYPTION_KEY is not configured")
try:
return Fernet(str(key).encode("ascii"))
except (TypeError, ValueError) as exc:
raise AiKeyEncryptionError("AI_KEY_ENCRYPTION_KEY is invalid") from exc