"""模型 API Key 的服务端加密边界。""" import base64 import hashlib from cryptography.fernet import Fernet, InvalidToken from django.conf import settings from common.exceptions import AgentConfigurationError def _fernet() -> Fernet: """从独立部署密钥派生 Fernet 密钥,避免直接复用原始配置文本。""" secret = str(getattr(settings, "MODEL_API_KEY_ENCRYPTION_KEY", "") or "").strip() if len(secret) < 32: raise AgentConfigurationError("模型密钥加密主密钥未配置或长度不足。") derived = hashlib.sha256(secret.encode("utf-8")).digest() return Fernet(base64.urlsafe_b64encode(derived)) def encrypt_api_key(api_key: str) -> str: """加密 API Key;密文可以入库,但不得出现在页面和日志中。""" return _fernet().encrypt(api_key.encode("utf-8")).decode("ascii") def decrypt_api_key(ciphertext: str) -> str: """解密 API Key,并把密钥轮换或数据损坏转换为稳定配置错误。""" try: return _fernet().decrypt(ciphertext.encode("ascii")).decode("utf-8") except (InvalidToken, UnicodeError, ValueError) as exc: raise AgentConfigurationError("模型 API Key 无法解密,请重新配置。") from exc