本文目录导读:

对于Python脚本中敏感数据的加密存储,推荐以下几种安全方案:
使用Fernet对称加密(推荐)
from cryptography.fernet import Fernet
import base64
import os
class SecureCache:
def __init__(self, key=None):
# 如果没有提供密钥,生成新密钥
if key is None:
key = Fernet.generate_key()
self.key = key
self.cipher = Fernet(key)
def encrypt_data(self, data: bytes) -> bytes:
"""加密数据"""
return self.cipher.encrypt(data)
def decrypt_data(self, encrypted_data: bytes) -> bytes:
"""解密数据"""
return self.cipher.decrypt(encrypted_data)
def save_encrypted(self, filepath: str, data: bytes):
"""保存加密数据到文件"""
encrypted = self.encrypt_data(data)
with open(filepath, 'wb') as f:
f.write(encrypted)
def load_encrypted(self, filepath: str) -> bytes:
"""从文件加载加密数据"""
with open(filepath, 'rb') as f:
encrypted = f.read()
return self.decrypt_data(encrypted)
# 使用示例
cache = SecureCache()
# 加密敏感数据
sensitive_data = b"password123"
encrypted = cache.encrypt_data(sensitive_data)
# 解密
decrypted = cache.decrypt_data(encrypted)
使用密钥管理服务
import os
import json
from cryptography.fernet import Fernet
from keyring import get_password, set_password
class SecureKeyManager:
"""安全密钥管理器"""
def __init__(self, service_name="myapp"):
self.service_name = service_name
self._load_or_create_key()
def _load_or_create_key(self):
"""从系统密钥环加载或创建密钥"""
stored_key = get_password(self.service_name, "encryption_key")
if stored_key:
self.key = stored_key.encode()
else:
self.key = Fernet.generate_key()
set_password(self.service_name, "encryption_key", self.key.decode())
self.cipher = Fernet(self.key)
def encrypt(self, data: str) -> str:
return self.cipher.encrypt(data.encode()).decode()
def decrypt(self, encrypted_data: str) -> str:
return self.cipher.decrypt(encrypted_data.encode()).decode()
# 使用系统密钥环安全存储
key_manager = SecureKeyManager()
encrypted = key_manager.encrypt("api_key_12345")
decrypted = key_manager.decrypt(encrypted)
使用环境变量 + 加密
import os
import base64
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
class EnvironmentSecureCache:
def __init__(self, password_env_var="CACHE_PASSWORD"):
# 从环境变量获取密码
password = os.environ.get(password_env_var)
if not password:
raise ValueError(f"环境变量 {password_env_var} 未设置")
# 使用PBKDF2派生密钥
salt = b'fixed_salt_16_bytes' # 实际应用中应该随机生成并存储
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
self.cipher = Fernet(key)
def encrypt(self, data):
return self.cipher.encrypt(data.encode() if isinstance(data, str) else data)
def decrypt(self, encrypted_data):
return self.cipher.decrypt(encrypted_data).decode()
# 设置环境变量(生产环境应通过安全方式设置)
# os.environ["CACHE_PASSWORD"] = "your_strong_password"
使用HSM或云密钥管理服务
import boto3
from botocore.exceptions import ClientError
import base64
class AWSKMSEncryption:
"""使用AWS KMS进行加密"""
def __init__(self, key_id):
self.kms = boto3.client('kms')
self.key_id = key_id
def encrypt(self, data: str) -> bytes:
response = self.kms.encrypt(
KeyId=self.key_id,
Plaintext=data.encode()
)
return response['CiphertextBlob']
def decrypt(self, encrypted_data: bytes) -> str:
response = self.kms.decrypt(
CiphertextBlob=encrypted_data
)
return response['Plaintext'].decode()
# 使用示例
# kms = AWSKMSEncryption('your-kms-key-id')
# encrypted = kms.encrypt("敏感数据")
# decrypted = kms.decrypt(encrypted)
内存安全缓存
import hashlib
import hmac
import os
from typing import Optional, Dict
class MemorySecureCache:
"""内存中的安全缓存"""
def __init__(self, master_key: bytes):
self.master_key = master_key
self.cache: Dict[str, bytes] = {}
def _derive_key(self, cache_key: str) -> bytes:
"""为每个缓存项派生唯一密钥"""
return hmac.new(
self.master_key,
cache_key.encode(),
hashlib.sha256
).digest()[:32]
def store(self, key: str, value: str):
"""安全存储数据"""
encrypt_key = self._derive_key(key)
from cryptography.fernet import Fernet
import base64
cipher = Fernet(base64.urlsafe_b64encode(encrypt_key))
self.cache[key] = cipher.encrypt(value.encode())
def retrieve(self, key: str) -> Optional[str]:
"""安全检索数据"""
if key not in self.cache:
return None
encrypt_key = self._derive_key(key)
from cryptography.fernet import Fernet
import base64
cipher = Fernet(base64.urlsafe_b64encode(encrypt_key))
return cipher.decrypt(self.cache[key]).decode()
def clear(self):
"""清除所有缓存"""
self.cache.clear()
# 使用示例
master_key = os.urandom(32)
secure_cache = MemorySecureCache(master_key)
secure_cache.store("api_key", "sk-1234567890")
api_key = secure_cache.retrieve("api_key")
最佳实践建议
-
密钥管理:
- 永远不要在代码中硬编码密钥
- 使用环境变量、密钥管理服务或硬件安全模块
- 定期轮换密钥
-
数据分类:
- 只在必要时缓存敏感数据
- 设置合理的过期时间
- 实施访问控制
-
安全配置:
class SecureConfig: # 从安全源加载配置 @staticmethod def load_config(): config = { 'encryption_key': os.environ.get('ENCRYPTION_KEY'), 'cache_ttl': 3600, # 1小时 'max_cache_size': 100 * 1024 * 1024, # 100MB } return config -
日志和审计:
- 记录访问尝试
- 监控异常行为
- 实施告警机制
选择合适的方案取决于你的安全需求、基础设施和预算,对于大多数应用,使用Fernet对称加密配合密钥管理服务是最佳选择。