主要更新: - 更新代理商端文档,明确项目由品牌方分配流程 - 新增Brief配置详情页(已配置)设计稿 - 完善工作台紧急待办中品牌新任务功能 - 整理Pencil设计文件中代理商端页面顺序 - 新增后端FastAPI框架及核心API - 新增前端Next.js页面和组件库 - 添加.gitignore排除构建和缓存文件 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
85 lines
1.7 KiB
Python
85 lines
1.7 KiB
Python
"""
|
||
加密工具
|
||
API Key 加解密
|
||
"""
|
||
import base64
|
||
import os
|
||
from cryptography.fernet import Fernet
|
||
from cryptography.hazmat.primitives import hashes
|
||
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
||
|
||
from app.config import settings
|
||
|
||
|
||
def _get_fernet() -> Fernet:
|
||
"""
|
||
获取 Fernet 加密器
|
||
使用应用的 SECRET_KEY 派生加密密钥
|
||
"""
|
||
# 使用 PBKDF2 从 SECRET_KEY 派生 32 字节密钥
|
||
kdf = PBKDF2HMAC(
|
||
algorithm=hashes.SHA256(),
|
||
length=32,
|
||
salt=b"miaosi-api-key-salt", # 固定 salt,生产环境应配置为环境变量
|
||
iterations=100000,
|
||
)
|
||
key = base64.urlsafe_b64encode(
|
||
kdf.derive(settings.SECRET_KEY.encode())
|
||
)
|
||
return Fernet(key)
|
||
|
||
|
||
def encrypt_api_key(api_key: str) -> str:
|
||
"""
|
||
加密 API Key
|
||
|
||
Args:
|
||
api_key: 明文 API Key
|
||
|
||
Returns:
|
||
加密后的 Base64 字符串
|
||
"""
|
||
if not api_key:
|
||
return ""
|
||
|
||
fernet = _get_fernet()
|
||
encrypted = fernet.encrypt(api_key.encode())
|
||
return encrypted.decode()
|
||
|
||
|
||
def decrypt_api_key(encrypted: str) -> str:
|
||
"""
|
||
解密 API Key
|
||
|
||
Args:
|
||
encrypted: 加密的 API Key
|
||
|
||
Returns:
|
||
明文 API Key
|
||
"""
|
||
if not encrypted:
|
||
return ""
|
||
|
||
fernet = _get_fernet()
|
||
decrypted = fernet.decrypt(encrypted.encode())
|
||
return decrypted.decode()
|
||
|
||
|
||
def mask_api_key(api_key: str) -> str:
|
||
"""
|
||
脱敏 API Key
|
||
|
||
Args:
|
||
api_key: API Key(明文或加密均可)
|
||
|
||
Returns:
|
||
脱敏后的字符串,如 "sk-1234****5678"
|
||
"""
|
||
if not api_key:
|
||
return ""
|
||
|
||
if len(api_key) <= 8:
|
||
return "****"
|
||
|
||
return f"{api_key[:4]}****{api_key[-4:]}"
|