本文目录导读:

Python脚本中加密存储配置信息有多种方法,我来介绍几种常用的安全方案:
使用 cryptography 库(推荐)
from cryptography.fernet import Fernet
import base64
import json
from pathlib import Path
class ConfigEncryptor:
def __init__(self, key_file="config_key.key"):
self.key_file = key_file
self.cipher = None
def generate_key(self):
"""生成加密密钥并保存"""
key = Fernet.generate_key()
with open(self.key_file, 'wb') as f:
f.write(key)
return key
def load_key(self):
"""加载加密密钥"""
with open(self.key_file, 'rb') as f:
key = f.read()
self.cipher = Fernet(key)
return key
def encrypt_config(self, config_dict):
"""加密配置字典"""
if not self.cipher:
self.load_key()
config_json = json.dumps(config_dict).encode()
encrypted = self.cipher.encrypt(config_json)
return encrypted
def decrypt_config(self, encrypted_data):
"""解密配置数据"""
if not self.cipher:
self.load_key()
decrypted = self.cipher.decrypt(encrypted_data)
return json.loads(decrypted.decode())
# 使用示例
def main():
# 1. 首次使用:生成密钥并加密配置
encryptor = ConfigEncryptor()
# 生成密钥(仅执行一次)
if not Path("config_key.key").exists():
encryptor.generate_key()
print("密钥文件已生成,请妥善保管!")
# 2. 加密配置
config = {
"database": {
"host": "localhost",
"port": 3306,
"username": "admin",
"password": "SecretPassword123!"
},
"api": {
"key": "api-key-123456",
"secret": "api-secret-789012"
}
}
encrypted_data = encryptor.encrypt_config(config)
# 保存加密后的配置
with open("config.encrypted", "wb") as f:
f.write(encrypted_data)
# 3. 解密配置使用
with open("config.encrypted", "rb") as f:
encrypted_data = f.read()
decrypted_config = encryptor.decrypt_config(encrypted_data)
# 使用配置
db_password = decrypted_config["database"]["password"]
api_key = decrypted_config["api"]["key"]
print(f"数据库密码: {db_password}")
print(f"API密钥: {api_key}")
if __name__ == "__main__":
main()
使用环境变量 + 配置加密(更安全)
import os
from cryptography.fernet import Fernet
import base64
import json
class SecureConfigManager:
def __init__(self):
# 从环境变量获取主密钥
self.master_key = os.environ.get('CONFIG_MASTER_KEY')
if not self.master_key:
raise ValueError("请设置 CONFIG_MASTER_KEY 环境变量")
# 将主密钥转换为Fernet密钥
self.fernet_key = base64.urlsafe_b64encode(
self.master_key.encode()[:32].ljust(32, b'\0')
)
self.cipher = Fernet(self.fernet_key)
def encrypt_value(self, value):
"""加密单个配置值"""
return self.cipher.encrypt(value.encode()).decode()
def decrypt_value(self, encrypted_value):
"""解密单个配置值"""
return self.cipher.decrypt(encrypted_value.encode()).decode()
def save_config(self, config_dict, filename="config.json"):
"""保存加密的配置文件"""
encrypted_config = {}
for key, value in config_dict.items():
encrypted_config[key] = self.encrypt_value(str(value))
with open(filename, 'w') as f:
json.dump(encrypted_config, f, indent=2)
def load_config(self, filename="config.json"):
"""加载并解密配置文件"""
with open(filename, 'r') as f:
encrypted_config = json.load(f)
decrypted_config = {}
for key, value in encrypted_config.items():
decrypted_config[key] = self.decrypt_value(value)
return decrypted_config
# 使用示例
def main():
# 设置环境变量(实际使用时应设置为系统环境变量)
os.environ['CONFIG_MASTER_KEY'] = 'your-very-secure-master-key-32chars'
manager = SecureConfigManager()
# 加密保存配置
config = {
"DB_PASSWORD": "super_secret_password",
"API_KEY": "sk-test-123456",
"EMAIL_PASSWORD": "email_pass_2024"
}
manager.save_config(config)
print("配置已加密保存")
# 读取并使用配置
loaded_config = manager.load_config()
print(f"数据库密码: {loaded_config['DB_PASSWORD']}")
if __name__ == "__main__":
main()
使用 keyring 系统密钥环(最安全)
import keyring
import json
class KeyringConfigManager:
def __init__(self, service_name="MyPythonApp"):
self.service_name = service_name
def save_to_keyring(self, key, value):
"""保存到系统密钥环"""
keyring.set_password(self.service_name, key, value)
def get_from_keyring(self, key):
"""从系统密钥环获取"""
return keyring.get_password(self.service_name, key)
def delete_from_keyring(self, key):
"""从系统密钥环删除"""
keyring.delete_password(self.service_name, key)
def save_config_dict(self, config_dict):
"""保存配置字典到密钥环"""
for key, value in config_dict.items():
self.save_to_keyring(key, value)
def get_config_dict(self, keys):
"""从密钥环获取配置字典"""
config = {}
for key in keys:
value = self.get_from_keyring(key)
if value:
config[key] = value
return config
# 使用示例
def main():
manager = KeyringConfigManager()
# 保存配置到系统密钥环
config = {
"database_host": "localhost",
"database_user": "myuser",
"database_password": "secret123"
}
manager.save_config_dict(config)
print("配置已保存到系统密钥环")
# 读取配置
keys_to_load = ["database_host", "database_user", "database_password"]
loaded_config = manager.get_config_dict(keys_to_load)
print(f"数据库密码: {loaded_config['database_password']}")
if __name__ == "__main__":
main()
推荐的安全实践
"""
最佳实践配置文件结构:
project/
├── config/
│ ├── config.json # 非敏感配置
│ └── config.encrypted # 加密的敏感配置
├── keys/
│ └── master.key # 主密钥文件(从不提交到Git)
├── .env # 环境变量(不提交到Git)
├── .gitignore
└── your_script.py
"""
# .env 文件示例
CONFIG_MASTER_KEY=your_master_key_here
DB_HOST=localhost
DB_PORT=3306
# .gitignore 添加
keys/
.env
*.encrypted
config_key.key
"""
安全建议:
1. 永远不要将密钥硬编码在代码中
2. 使用环境变量传递密钥
3. 将密钥文件添加到 .gitignore
4. 使用不同的密钥用于开发和生产环境
5. 考虑使用专业的密钥管理服务(如 AWS KMS, Azure Key Vault)
6. 定期轮换密钥
7. 限制密钥访问权限
"""
# 综合使用示例
import os
from pathlib import Path
from cryptography.fernet import Fernet
class ProductionConfigManager:
"""生产环境配置管理器"""
def __init__(self):
# 优先使用环境变量,其次是密钥文件
self.master_key = os.environ.get('CONFIG_MASTER_KEY')
if not self.master_key:
key_file = Path('keys/master.key')
if key_file.exists():
self.master_key = key_file.read_text().strip()
else:
# 生成新的密钥
self.master_key = Fernet.generate_key().decode()
key_file.parent.mkdir(exist_ok=True)
key_file.write_text(self.master_key)
key_file.chmod(0o600) # 仅所有者可读写
self.cipher = Fernet(self.master_key.encode() if isinstance(self.master_key, str) else self.master_key)
def encrypt(self, data):
if isinstance(data, str):
data = data.encode()
return self.cipher.encrypt(data)
def decrypt(self, encrypted_data):
return self.cipher.decrypt(encrypted_data)
# 使用示例
config_manager = ProductionConfigManager()
encrypted = config_manager.encrypt("sensitive_data")
decrypted = config_manager.decrypt(encrypted)
安装依赖
# 安装所需库 pip install cryptography keyring # keyring 可能需要额外系统依赖 # Ubuntu/Debian: sudo apt-get install libsecret-1-dev # macOS: brew install libsecret
选择建议
- 个人项目:使用 cryptography 库 + 密钥文件
- 团队项目:使用环境变量 + cryptography
- 企业应用:使用系统密钥环或专业密钥管理服务
- 云原生应用:使用云服务商提供的密钥管理服务
没有任何加密方法是绝对安全的,关键是找到安全性和便利性的平衡点。