需求
开发中需要将配置文件中的敏感信息非明文展示,如数据库账户密码等,本文使用python中的第三方库完成加密解密工作,环境为python3.8
实现
1.加密
from configparser_crypt import ConfigParserCrypt
# 加密文件名称,按需修改
file = 'config_dev.encrypted'
conf_file = ConfigParserCrypt()
# 创建新的aes_key
conf_file.generate_key()
# 创建完的aes_key请保存好,后续需要用来解密
aes_key = conf_file.aes_key
print(aes_key)
# 创建自己的配置项,注意格式,这里键值对里的值我用字典的话后续用get方法报错,改成json格式用json.loads方法获取后正常,可自行尝试有无其他格式或方法
# 该加密库继承自ConfigParser,关于配置可自行搜索相关用法
conf_file.add_section("config")
conf_file["config"] = {"type": "{\"alias\": \"mysql\"}",
"database": "{\"host\": \"127.0.0.1\", \"user\": \"username\", \"password\": \"yourpassword\", \"port\": \"3306\",\"database\": \"databasename\"}",
"redis": "{\"host\": \"127.0.0.1\", \"port\": \"6379\", \"password\": \"\"}"}
# 写入加密文件
with open(file, 'wb') as file_handle:
conf_file.write_encrypted(file_handle)
# 将加密文件放入项目配置文件夹下
2.解密
from configparser_crypt import ConfigParserCrypt
# 这边最后是把配置项转成字典
config = dict()
# 加密好的配置文件路径
file_path='your_file_path'
conf_file = ConfigParserCrypt()
# 使用之前生成的aes_key
conf_file.aes_key = YOUR_KEY
conf_file.read_encrypted(file_path)
# 获取配置下中section为config的option,并获取对应的值,存入字典
for key in conf_file.options('config'):
value = conf_file.get('config', key)
config[key] = json.loads(value)
# 最后返回配置项字典config就可以使用了
- 后续更新无需手动输入数据,可直接读取配置文件
import configparser
import json
from configparser_crypt import ConfigParserCrypt
def encrypt_config(config_path: str, encrypted_file_path: str, key_path: str, key_name: str) -> bytes:
"""
读取ini格式配置文件并加密,密钥会自动保存或更新到对应文件
:param config_path: ini格式配置文件路径,文件中section需为config,如有变化需修改代码 例:r'D:\projects\config_dev.ini'
:param encrypted_file_path:加密后的文件路径及名称 例:r'D:\projects\temp\tests\encrypt_test.encrypted'
:param key_path:生成的密钥保存文件路径,文件需存在,也可以是txt格式 例:r'D:\projects\temp\tests\login_key.py'
:param key_name:密钥名称 例:'CONFIG_KEY'
:return: bytes 返回密钥(方便测试)
"""
# 创建字典保存读取到的配置信息
config = dict()
config_parser = configparser.ConfigParser()
config_parser.read(config_path)
for key in config_parser.options('config'):
value = config_parser.get('config', key)
config[key] = json.loads(value)
# 创建加密类,开始加密
conf_file = ConfigParserCrypt()
# 生成密钥
conf_file.generate_key()
# 取得密钥
aes_key = conf_file.aes_key
# 将密钥存入对应文件,若不存在则添加在最后一行,如想手动更新密钥请注释下面10行
with open(key_path, 'r') as fr:
datas = fr.readlines()
for i in range(len(datas)):
if datas[i].strip()[:len(key_name)] == key_name:
datas[i] = '{} = {}\n'.format(key_name,aes_key)
break
else:
datas.append('{} = {}\n'.format(key_name,aes_key))
with open(key_path, 'w') as fw:
fw.writelines(datas)
# 添加配置信息
conf_file.add_section("config")
temp = dict()
for key, value in config.items():
temp[key] = json.dumps(value)
conf_file['config'] = temp
# 保存加密文件
with open(encrypted_file_path, 'wb') as file_handle:
conf_file.write_encrypted(file_handle)
return aes_key
def decrypt_config(file_path: str, key_path: str, key_name: str) -> dict:
"""
将加密的配置文件解密,测试用
:param file_path: 加密文件路径
:param key_path: 密钥文件路径
:param key_name: 密钥名称
:return: dict 配置文件字典
"""
# 创建字典用来保存配置信息
config = dict()
conf_file = ConfigParserCrypt()
# 读取密钥
with open(key_path, 'r') as fr:
datas = fr.readlines()
for line in datas:
if line.strip()[:len(key_name)] == key_name:
key = eval(line.strip().split('=',1)[-1].strip())
# 设置密钥
conf_file.aes_key = key
# 解密
conf_file.read_encrypted(file_path)
# 保存至config
for key in conf_file.options('config'):
value = conf_file.get('config', key)
config[key] = json.loads(value)
return config
if __name__ == '__main__':
# 测试
config_path = r'D:\projects\config_dev.ini'
encrypted_file_path = r'D:\projects\temp\tests\encrypt_test.encrypted'
key_path = r'D:\projects\temp\tests\login_key.py'
key_name = 'CONFIG_READ_KEY'
key = encrypt_config(config_path, encrypted_file_path, key_path, key_name)
config = decrypt_config(encrypted_file_path, key_path, key_name)
print(config)