35 lines
1.2 KiB
Python
35 lines
1.2 KiB
Python
"""模型 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
|