""" app/utils/fernet_utils.py — Fernet 加解密工具(按 Lead 规范路径) FERNET_KEY 走环境变量,绝不进代码库(基石B)。 此模块是 app/core/security.py 中 Fernet 功能的独立导出, 供 AIE / worker 层直接 import,无需依赖 FastAPI 上下文。 """ import logging from cryptography.fernet import Fernet, InvalidToken from app.core.config import get_settings logger = logging.getLogger(__name__) _fernet_instance: Fernet | None = None def _get_fernet() -> Fernet: global _fernet_instance if _fernet_instance is None: settings = get_settings() _fernet_instance = Fernet(settings.FERNET_KEY.encode()) return _fernet_instance def encrypt_key(plain_key: str) -> str: """ 加密 API Key,返回密文字符串。 调用方绝不打印 plain_key(基石B)。 """ return _get_fernet().encrypt(plain_key.encode()).decode() def decrypt_key(encrypted_key: str) -> str: """ 解密 API Key。只在 Celery worker 内部调用。 解密结果只活在调用函数的局部变量,不落盘、不打日志。 """ try: return _get_fernet().decrypt(encrypted_key.encode()).decode() except InvalidToken: logger.error("Fernet decryption failed: token invalid or key rotated") raise ValueError("API key decryption failed") def mask_key(plain_key: str) -> str: """只返回后4位(展示用,不暴露完整 key)。""" return plain_key[-4:] if len(plain_key) >= 4 else "****"