308 lines
8.5 KiB
Python
308 lines
8.5 KiB
Python
"""
|
|
加密工具模块 - 提供API Key的加密和解密功能
|
|
"""
|
|
|
|
import base64
|
|
import hashlib
|
|
import os
|
|
from typing import Optional
|
|
from cryptography.fernet import Fernet
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
|
|
|
|
|
class SimpleEncryptor:
|
|
"""简单的加密器,用于API Key的安全存储"""
|
|
|
|
def __init__(self, password: str = None):
|
|
"""
|
|
初始化加密器
|
|
|
|
Args:
|
|
password: 主密码,如果为None则使用机器特征生成
|
|
"""
|
|
if password is None:
|
|
password = self._generate_machine_key()
|
|
|
|
self.password = password.encode() if isinstance(password, str) else password
|
|
self._fernet = None
|
|
|
|
def _generate_machine_key(self) -> str:
|
|
"""基于机器特征生成密钥"""
|
|
try:
|
|
import platform
|
|
import getpass
|
|
|
|
# 收集机器特征
|
|
features = [
|
|
platform.machine(),
|
|
platform.processor(),
|
|
platform.system(),
|
|
platform.node(),
|
|
getpass.getuser()
|
|
]
|
|
|
|
# 组合特征并生成哈希
|
|
combined = "".join(str(f) for f in features if f)
|
|
if not combined:
|
|
combined = "google_nano_default_key"
|
|
|
|
return hashlib.sha256(combined.encode()).hexdigest()[:32]
|
|
except Exception:
|
|
# 如果无法获取机器特征,使用默认值
|
|
return "google_nano_fallback_key_2024"
|
|
|
|
def _get_fernet(self) -> Fernet:
|
|
"""获取Fernet加密实例"""
|
|
if self._fernet is None:
|
|
# 使用PBKDF2从密码派生密钥
|
|
salt = b'google_nano_salt_2024' # 固定盐值,确保一致性
|
|
kdf = PBKDF2HMAC(
|
|
algorithm=hashes.SHA256(),
|
|
length=32,
|
|
salt=salt,
|
|
iterations=100000,
|
|
)
|
|
key = base64.urlsafe_b64encode(kdf.derive(self.password))
|
|
self._fernet = Fernet(key)
|
|
|
|
return self._fernet
|
|
|
|
def encrypt(self, plaintext: str) -> str:
|
|
"""
|
|
加密字符串
|
|
|
|
Args:
|
|
plaintext: 要加密的明文
|
|
|
|
Returns:
|
|
加密后的base64字符串
|
|
"""
|
|
if not plaintext:
|
|
return ""
|
|
|
|
try:
|
|
fernet = self._get_fernet()
|
|
encrypted_bytes = fernet.encrypt(plaintext.encode())
|
|
return base64.b64encode(encrypted_bytes).decode()
|
|
except Exception as e:
|
|
print(f"加密失败: {e}")
|
|
return plaintext # 如果加密失败,返回原文
|
|
|
|
def decrypt(self, ciphertext: str) -> str:
|
|
"""
|
|
解密字符串
|
|
|
|
Args:
|
|
ciphertext: 要解密的密文(base64编码)
|
|
|
|
Returns:
|
|
解密后的明文
|
|
"""
|
|
if not ciphertext:
|
|
return ""
|
|
|
|
try:
|
|
fernet = self._get_fernet()
|
|
encrypted_bytes = base64.b64decode(ciphertext.encode())
|
|
decrypted_bytes = fernet.decrypt(encrypted_bytes)
|
|
return decrypted_bytes.decode()
|
|
except Exception as e:
|
|
print(f"解密失败: {e}")
|
|
return ciphertext # 如果解密失败,返回原文(可能是明文存储)
|
|
|
|
def is_encrypted(self, text: str) -> bool:
|
|
"""
|
|
检查文本是否已加密
|
|
|
|
Args:
|
|
text: 要检查的文本
|
|
|
|
Returns:
|
|
是否为加密文本
|
|
"""
|
|
if not text:
|
|
return False
|
|
|
|
try:
|
|
# 尝试解密,如果成功且结果不同则说明是加密的
|
|
decrypted = self.decrypt(text)
|
|
return decrypted != text and len(decrypted) > 0
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
class ConfigEncryption:
|
|
"""配置文件加密管理器"""
|
|
|
|
def __init__(self, encryptor: SimpleEncryptor):
|
|
"""
|
|
初始化配置加密管理器
|
|
|
|
Args:
|
|
encryptor: 加密器实例
|
|
"""
|
|
self.encryptor = encryptor
|
|
|
|
def encrypt_api_keys(self, config: dict) -> dict:
|
|
"""
|
|
加密配置中的API Keys
|
|
|
|
Args:
|
|
config: 配置字典
|
|
|
|
Returns:
|
|
加密后的配置字典
|
|
"""
|
|
if not config or "api_keys" not in config:
|
|
return config
|
|
|
|
# 创建配置副本
|
|
encrypted_config = config.copy()
|
|
encrypted_config["api_keys"] = []
|
|
|
|
for key_config in config.get("api_keys", []):
|
|
encrypted_key = key_config.copy()
|
|
|
|
# 加密API Key值
|
|
api_key_value = key_config.get("value", "")
|
|
if api_key_value and not self.encryptor.is_encrypted(api_key_value):
|
|
encrypted_key["value"] = self.encryptor.encrypt(api_key_value)
|
|
encrypted_key["encrypted"] = True
|
|
|
|
encrypted_config["api_keys"].append(encrypted_key)
|
|
|
|
# 标记加密状态
|
|
encrypted_config.setdefault("settings", {})["encryption_enabled"] = True
|
|
|
|
return encrypted_config
|
|
|
|
def decrypt_api_keys(self, config: dict) -> dict:
|
|
"""
|
|
解密配置中的API Keys
|
|
|
|
Args:
|
|
config: 加密的配置字典
|
|
|
|
Returns:
|
|
解密后的配置字典
|
|
"""
|
|
if not config or "api_keys" not in config:
|
|
return config
|
|
|
|
# 创建配置副本
|
|
decrypted_config = config.copy()
|
|
decrypted_config["api_keys"] = []
|
|
|
|
for key_config in config.get("api_keys", []):
|
|
decrypted_key = key_config.copy()
|
|
|
|
# 解密API Key值
|
|
if key_config.get("encrypted", False):
|
|
encrypted_value = key_config.get("value", "")
|
|
if encrypted_value:
|
|
decrypted_key["value"] = self.encryptor.decrypt(encrypted_value)
|
|
decrypted_key["encrypted"] = False
|
|
|
|
decrypted_config["api_keys"].append(decrypted_key)
|
|
|
|
return decrypted_config
|
|
|
|
def get_decrypted_key_value(self, key_config: dict) -> str:
|
|
"""
|
|
获取解密后的API Key值
|
|
|
|
Args:
|
|
key_config: API Key配置
|
|
|
|
Returns:
|
|
解密后的API Key值
|
|
"""
|
|
if not key_config:
|
|
return ""
|
|
|
|
api_key_value = key_config.get("value", "")
|
|
if key_config.get("encrypted", False) and api_key_value:
|
|
return self.encryptor.decrypt(api_key_value)
|
|
|
|
return api_key_value
|
|
|
|
|
|
# 全局加密器实例(单例模式)
|
|
_global_encryptor: Optional[SimpleEncryptor] = None
|
|
_global_config_encryption: Optional[ConfigEncryption] = None
|
|
|
|
|
|
def get_encryptor(password: str = None) -> SimpleEncryptor:
|
|
"""
|
|
获取全局加密器实例
|
|
|
|
Args:
|
|
password: 主密码
|
|
|
|
Returns:
|
|
加密器实例
|
|
"""
|
|
global _global_encryptor
|
|
|
|
if _global_encryptor is None:
|
|
_global_encryptor = SimpleEncryptor(password)
|
|
|
|
return _global_encryptor
|
|
|
|
|
|
def get_config_encryption(password: str = None) -> ConfigEncryption:
|
|
"""
|
|
获取全局配置加密管理器实例
|
|
|
|
Args:
|
|
password: 主密码
|
|
|
|
Returns:
|
|
配置加密管理器实例
|
|
"""
|
|
global _global_config_encryption
|
|
|
|
if _global_config_encryption is None:
|
|
encryptor = get_encryptor(password)
|
|
_global_config_encryption = ConfigEncryption(encryptor)
|
|
|
|
return _global_config_encryption
|
|
|
|
|
|
def simple_encrypt(text: str) -> str:
|
|
"""
|
|
简单加密函数(使用默认加密器)
|
|
|
|
Args:
|
|
text: 要加密的文本
|
|
|
|
Returns:
|
|
加密后的文本
|
|
"""
|
|
encryptor = get_encryptor()
|
|
return encryptor.encrypt(text)
|
|
|
|
|
|
def simple_decrypt(text: str) -> str:
|
|
"""
|
|
简单解密函数(使用默认加密器)
|
|
|
|
Args:
|
|
text: 要解密的文本
|
|
|
|
Returns:
|
|
解密后的文本
|
|
"""
|
|
encryptor = get_encryptor()
|
|
return encryptor.decrypt(text)
|
|
|
|
|
|
# 检查是否可用加密功能
|
|
def is_encryption_available() -> bool:
|
|
"""检查是否可以使用加密功能"""
|
|
try:
|
|
from cryptography.fernet import Fernet
|
|
return True
|
|
except ImportError:
|
|
return False |