ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

手把手教你用Python脚本实现Keil编译后自动AES加密(附工程目录陷阱解析)

2026/8/13 14:14:49 拓冰建站 浏览量
手把手教你用Python脚本实现Keil编译后自动AES加密(附工程目录陷阱解析)

手把手教你用Python脚本实现Keil编译后自动AES加密(附工程目录陷阱解析)

在嵌入式开发中,固件升级是常见需求,而保障传输安全则是重中之重。AES加密因其高效可靠成为首选方案,但每次手动加密bin文件既耗时又容易出错。本文将带你用Python脚本实现Keil编译后自动完成AES加密的全流程,特别针对工程目录与脚本路径不一致这一"隐形杀手"提供完整解决方案。

1. 环境准备与基础配置

1.1 工具链检查

开始前请确保已安装:

  • Keil MDK(建议≥5.25)
  • Python 3.8+(需安装pycryptodome库)
  • 目标芯片的Device Family Pack

验证Python环境:

pip install pycryptodome python -c "from Crypto.Cipher import AES; print('AES模块可用')"

1.2 加密密钥管理

推荐采用.ini文件存储密钥,避免硬编码风险。示例config.ini:

[aes] key = 2B7E151628AED2A6ABF7158809CF4F3C iv = 000102030405060708090A0B0C0D0E0F

注意:实际项目中应通过密钥派生函数动态生成iv,此处简化演示

2. Python加密脚本开发

2.1 基础加密函数实现

创建aes_encryptor.py,核心代码如下:

from Crypto.Cipher import AES from Crypto.Util.Padding import pad import configparser def encrypt_file(input_path, output_path): config = configparser.ConfigParser() config.read('config.ini') key = bytes.fromhex(config['aes']['key']) iv = bytes.fromhex(config['aes']['iv']) cipher = AES.new(key, AES.MODE_CBC, iv) with open(input_path, 'rb') as f: plaintext = f.read() ciphertext = cipher.encrypt(pad(plaintext, AES.block_size)) with open(output_path, 'wb') as f: f.write(ciphertext)

2.2 增强型参数处理

改进版本支持命令行参数:

import sys import os if __name__ == "__main__": if len(sys.argv) != 3: print("Usage: python aes_encryptor.py <input_bin> <output_enc>") sys.exit(1) input_file = os.path.abspath(sys.argv[1]) output_file = os.path.abspath(sys.argv[2]) if not os.path.exists(input_file): print(f"Error: Input file {input_file} not found") sys.exit(2) encrypt_file(input_file, output_file) print(f"Success: Encrypted file saved to {output_file}")

3. Keil工程集成方案

3.1 编译后命令配置

在Keil中设置编译后自动执行:

  1. 打开Options for Target → User
  2. 在"After Build/Rebuild"勾选"Run #1"
  3. 输入命令:
python path/to/aes_encryptor.py ./Objects/your_firmware.bin ./Objects/encrypted.bin

关键参数说明:

参数说明示例值
%L工程文件路径C:/Projects/STM32
@L工程名称MyProject
.\工程所在目录-

3.2 目录陷阱解决方案

针对工程与脚本路径不一致问题,提供三种可靠方案:

方案一:绝对路径传递

python D:\scripts\aes_encryptor.py ^ %D\Objects\%@L.bin ^ %D\Objects\%@L_enc.bin

方案二:环境变量法

  1. 设置系统变量PY_SCRIPT_DIR
  2. Keil命令改为:
python %PY_SCRIPT_DIR%\aes_encryptor.py ...

方案三:批处理封装创建run_encrypt.bat

@echo off pushd "%~dp0" python aes_encryptor.py %* popd

Keil中调用:

cmd /c path/to/run_encrypt.bat ...

4. 调试与异常处理

4.1 常见错误排查表

现象可能原因解决方案
"python不是内部命令"Python未加入PATH使用完整python路径
找不到config.ini工作目录错误使用os.path.dirname(__file__)定位
加密文件为空源文件读取失败检查文件权限和路径
密钥错误.ini格式问题验证hex字符串长度

4.2 日志增强实践

在脚本中添加日志记录:

import logging logging.basicConfig( filename='encryption.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s' ) try: encrypt_file(input_file, output_file) except Exception as e: logging.error(f"加密失败: {str(e)}") raise

5. 进阶优化技巧

5.1 多线程加密加速

当需要批量处理时:

from concurrent.futures import ThreadPoolExecutor def batch_encrypt(file_pairs): with ThreadPoolExecutor() as executor: futures = [ executor.submit(encrypt_file, inp, out) for inp, out in file_pairs ] for future in futures: future.result() # 触发异常传播

5.2 固件校验机制

加密后添加CRC校验:

import zlib def add_crc(output_path): with open(output_path, 'rb+') as f: data = f.read() crc = zlib.crc32(data).to_bytes(4, 'big') f.write(crc)

实际项目中,我们团队发现最稳定的方案是方案三的批处理封装,配合日志记录可以快速定位90%以上的路径相关问题。当工程结构复杂时,建议在脚本初始处打印当前工作目录和参数解析结果,这对调试有极大帮助。