Python脚本如何加密存储配置信息

wen python案例 28

本文目录导读:

Python脚本如何加密存储配置信息

  1. 使用 cryptography 库(推荐)
  2. 使用环境变量 + 配置加密(更安全)
  3. 使用 keyring 系统密钥环(最安全)
  4. 推荐的安全实践
  5. 安装依赖
  6. 选择建议

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

选择建议

  1. 个人项目:使用 cryptography 库 + 密钥文件
  2. 团队项目:使用环境变量 + cryptography
  3. 企业应用:使用系统密钥环或专业密钥管理服务
  4. 云原生应用:使用云服务商提供的密钥管理服务

没有任何加密方法是绝对安全的,关键是找到安全性和便利性的平衡点。

抱歉,评论功能暂时关闭!