feat: AI聊天室多Agent协作讨论平台
- 实现Agent管理,支持AI辅助生成系统提示词 - 支持多个AI提供商(OpenRouter、智谱、MiniMax等) - 实现聊天室和讨论引擎 - WebSocket实时消息推送 - 前端使用React + Ant Design - 后端使用FastAPI + MongoDB Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
97
backend/utils/encryption.py
Normal file
97
backend/utils/encryption.py
Normal file
@@ -0,0 +1,97 @@
|
||||
"""
|
||||
加密工具模块
|
||||
用于API密钥的加密和解密
|
||||
"""
|
||||
import base64
|
||||
from cryptography.fernet import Fernet
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
||||
from loguru import logger
|
||||
|
||||
from config import settings
|
||||
|
||||
|
||||
def _get_fernet() -> Fernet:
|
||||
"""
|
||||
获取Fernet加密器实例
|
||||
使用配置的加密密钥派生加密密钥
|
||||
|
||||
Returns:
|
||||
Fernet加密器
|
||||
"""
|
||||
# 使用PBKDF2从密钥派生32字节密钥
|
||||
salt = b"ai_chatroom_salt" # 固定salt,实际生产环境应使用随机salt
|
||||
kdf = PBKDF2HMAC(
|
||||
algorithm=hashes.SHA256(),
|
||||
length=32,
|
||||
salt=salt,
|
||||
iterations=100000,
|
||||
)
|
||||
key = base64.urlsafe_b64encode(
|
||||
kdf.derive(settings.ENCRYPTION_KEY.encode())
|
||||
)
|
||||
return Fernet(key)
|
||||
|
||||
|
||||
def encrypt_api_key(api_key: str) -> str:
|
||||
"""
|
||||
加密API密钥
|
||||
|
||||
Args:
|
||||
api_key: 原始API密钥
|
||||
|
||||
Returns:
|
||||
加密后的密钥字符串
|
||||
"""
|
||||
if not api_key:
|
||||
return ""
|
||||
|
||||
try:
|
||||
fernet = _get_fernet()
|
||||
encrypted = fernet.encrypt(api_key.encode())
|
||||
return encrypted.decode()
|
||||
except Exception as e:
|
||||
logger.error(f"API密钥加密失败: {e}")
|
||||
raise ValueError("加密失败")
|
||||
|
||||
|
||||
def decrypt_api_key(encrypted_key: str) -> str:
|
||||
"""
|
||||
解密API密钥
|
||||
|
||||
Args:
|
||||
encrypted_key: 加密的密钥字符串
|
||||
|
||||
Returns:
|
||||
解密后的原始API密钥
|
||||
"""
|
||||
if not encrypted_key:
|
||||
return ""
|
||||
|
||||
try:
|
||||
fernet = _get_fernet()
|
||||
decrypted = fernet.decrypt(encrypted_key.encode())
|
||||
return decrypted.decode()
|
||||
except Exception as e:
|
||||
logger.error(f"API密钥解密失败: {e}")
|
||||
raise ValueError("解密失败,密钥可能已损坏或被篡改")
|
||||
|
||||
|
||||
def mask_api_key(api_key: str, visible_chars: int = 4) -> str:
|
||||
"""
|
||||
掩码API密钥,用于安全显示
|
||||
|
||||
Args:
|
||||
api_key: 原始API密钥
|
||||
visible_chars: 末尾可见字符数
|
||||
|
||||
Returns:
|
||||
掩码后的密钥 (如: ****abc1)
|
||||
"""
|
||||
if not api_key:
|
||||
return ""
|
||||
|
||||
if len(api_key) <= visible_chars:
|
||||
return "*" * len(api_key)
|
||||
|
||||
return "*" * (len(api_key) - visible_chars) + api_key[-visible_chars:]
|
||||
Reference in New Issue
Block a user