"""凭证加密模块(Fernet 对称加密) 用于加密存储 SSH 密钥、密码、API Key、平台 API 配置等敏感信息。 MASTER_KEY 从 .env 读取,不入库。 """ from functools import lru_cache from typing import Optional from cryptography.fernet import Fernet, InvalidToken from app.core.config import settings @lru_cache(maxsize=1) def _get_fernet() -> Fernet: """获取 Fernet 实例(进程内缓存,避免每次加解密重建;MASTER_KEY 未配置时抛错)""" key = settings.MASTER_KEY if not key: raise RuntimeError( "MASTER_KEY 未配置,无法加解密凭证。请在 .env 设置 MASTER_KEY," "生成命令:python -c 'from cryptography.fernet import Fernet; " "print(Fernet.generate_key().decode())'" ) return Fernet(key.encode() if isinstance(key, str) else key) def encrypt(plain: Optional[str]) -> Optional[str]: """加密明文,返回 token 字符串;空值原样返回 None""" if plain is None or plain == "": return None return _get_fernet().encrypt(plain.encode()).decode() def decrypt(token: Optional[str]) -> Optional[str]: """解密 token,返回明文;空值或解密失败返回 None""" if not token: return None try: return _get_fernet().decrypt(token.encode()).decode() except (InvalidToken, ValueError): return None