2. 固件镜像哈希计算

任务目标

为OTA固件更新流程实现镜像完整性校验的基础环节:计算固件二进制镜像的SHA-256哈希值。本案例聚焦哈希计算本身,不涉及签名、加密或传输协议。

环境与依赖

  • Python 3.8+(标准库 hashlib,无需第三方包)
  • 测试文件:任意二进制文件(如 firmware.bin),可用 dd 或 truncate 生成

关键完整代码

import hashlib
import sys
from pathlib import Path

CHUNK_SIZE = 64 * 1024  # 64KB,适配嵌入式镜像常见分块读取

def sha256_file(file_path: str) -> str:
    """计算文件的SHA-256哈希值,返回十六进制字符串。"""
    h = hashlib.sha256()
    with open(file_path, 'rb') as f:
        while chunk := f.read(CHUNK_SIZE):
            h.update(chunk)
    return h.hexdigest()

def sha256_bytes(data: bytes) -> str:
    """计算内存中字节数据的SHA-256哈希值(用于小镜像或测试)。"""
    return hashlib.sha256(data).hexdigest()

if __name__ == '__main__':
    if len(sys.argv) != 2:
        print('用法: python sha256_calc.py <firmware.bin>')
        sys.exit(1)
    path = sys.argv[1]
    if not Path(path).is_file():
        print(f'错误: 文件不存在 - {path}')
        sys.exit(1)
    digest = sha256_file(path)
    print(f'SHA-256 ({path}) = {digest}')

运行与验证

  1. 生成测试镜像(1MB随机数据):
    head -c 1048576 /dev/urandom > firmware.bin
  2. 运行脚本:
    python3 sha256_calc.py firmware.bin
  3. 预期输出格式:
    SHA-256 (firmware.bin) = <64位十六进制字符串>

验证方法

使用系统标准工具交叉校验,确认结果一致:

sha256sum firmware.bin

对比两个命令输出的64位十六进制字符串,完全一致即通过。若修改镜像任意一个字节(如 printf '\x01' | dd of=firmware.bin bs=1 seek=0 count=1 conv=notrunc),重新计算得到的哈希值应发生显著变化,用于确认哈希对镜像内容敏感。

常见问题

  • 大文件内存溢出:代码采用分块读取(64KB),避免一次性加载整个镜像到内存,适用于数MB至数百MB的固件。
  • 二进制模式:open 使用 'rb' 模式,防止Windows平台下换行符转换导致哈希值错误。
  • 与OTA集成:实际OTA流程中,设备端(C语言)可用 mbedtls_sha256 或 wolfSSL 实现相同算法;本案例的Python实现用于PC端生成参考哈希值或验证下载后镜像。