我们在上一篇的文章里Python 日志最佳实践:Loguru 快速上手,简单介绍了loguru模块基础使用,已经学会了如何去记录一些日志到文件里,方便用于后期排查和分析,现在有一个更加专业点的安全问题,有时我们将做好的项目或软件打包到客户那边去的时候,往往不想明文日志直接暴露出来,这样容易被分析,被破解,这时我们可以采用对日志加密的方式,这样当用户出现问题时,只需要把日志回传过来,本地做下解密,就可以分析了。
要加密日志的话,我们需要用到一个密码工具包,即cryptography模块。
#cryptography安装pip install cryptography接着我们来进一步优化上一篇文章中提到的logger_config.py文件,创建一个类,用来对消息的加密处理
import sysimport base64import hashlibfrom loguru import loggerfrom cryptography.fernet import Fernetclass EncryptedSink: def __init__(self, filename, password): #将配置的密码变成变成符合规范的32位的Key sha256_hash = hashlib.sha256(password.encode()).digest() key = base64.urlsafe_b64encode(sha256_hash) self.file = open(filename, "ab") self.fernet = Fernet(key) def write(self, message): #加密并写入 encrypted_data = self.fernet.encrypt(message.encode("utf-8")) self.file.write(encrypted_data + b"\n") self.file.flush()def setup_logging(log_path="app.log", password="hello123"): #默认密码hello123 #移除默认配置 logger.remove() #控制台输出可以设置为明文,方便开发时调试 logger.add(sys.stdout, level="DEBUG", format="<green>{time}</green> | <level>{level}</level> | {message}") #写到文件里的日志,则进行加密, 采用我们写好的Sink enc_sink = EncryptedSink(log_path, password) logger.add(enc_sink.write, level="DEBUG", enqueue=True)同样在main.py里做下输出测试
from loguru import loggerfrom logger_config import setup_loggingsetup_logging(log_path="app.enc.log") #在导入其他业务模块前执行, logger.debug("A debug message.")logger.info("An info message.")logger.success("A success message.")logger.warning("A warning message.")logger.error("An error message.")logger.critical("A critical message.")我们这时再查看下日志输出,就可以看到,数据已经被加密了

当然有加密,就必须要解密,我们就在本地再创建一个解密文件log_decryptor.py,专门用来解密这些日志文件,内容如下
import base64import hashlibfrom cryptography.fernet import Fernetdef decrypt_log_file(file_path, password="hello123"): """ 解密加密的日志文件并输出到控制台 :param file_path: 加密日志文件的路径 (如 app.enc.log) :param password: 加密时使用的原始字符串密码 """ # 1. 密钥还原逻辑 (必须与加密时完全一致) sha256_hash = hashlib.sha256(password.encode()).digest() key = base64.urlsafe_b64encode(sha256_hash) fernet = Fernet(key) print(f"{'='*20} 开始解密日志 {'='*20}") print(f"读取文件: {file_path}") print(f"使用密码: {password}\n") try: with open(file_path, "rb") as f: line_count = 0 for line in f: line = line.strip() if not line: continue try: # 2. 执行解密 decrypted_data = fernet.decrypt(line) # 3. 解码为字符串并打印 (去除末尾自带的换行符避免双倍换行) print(decrypted_data.decode("utf-8").strip()) line_count += 1 except Exception as e: print(f"[解密失败] 该行数据可能损坏或密钥错误: {e}") print(f"\n{'='*20} 解密完成 (共 {line_count} 行) {'='*20}") except FileNotFoundError: print(f"错误: 找不到文件 {file_path}") except Exception as e: print(f"系统错误: {e}")if __name__ == "__main__": # 使用示例 # 也可以配合命令行参数使用: sys.argv[1] target_file = "app.enc.log" my_password = "hello123" decrypt_log_file(target_file, my_password)看下解密后的日志输出

我们这样就简单完成的对日志的加密和解密,不过这里还可以做的更好一些,特别是我们密码部分,我们这里采用了硬编码方式,这种非常不建议,毕竟在逆向时很容易被看出来,如果用户软件有与服务器做通信,密码可以由服务器端传过去,这样客户那边是没办法直接看到的。需要对通信协议做分析才行。就需要更高的逆向技巧。