2、基础知识:固件、模型更新包、签名、哈希、完整性验证等核心概念解析

TinyML 设备的安全更新并非简单的“文件拷贝”,而是一条由多个密码学原语和工程组件构成的信任链。在深入签名方案之前,我们必须先厘清五个核心概念:固件(Firmware)、模型更新包(Model Update Package)、哈希(Hash)、签名(Signature)与完整性验证(Integrity Verification)。它们之间的关系决定了整个更新流程的安全边界。下图展示了这些概念在一条典型更新链路中的位置与交互关系:

TinyML 更新包信任链核心概念关系图 构建侧(开发机/CI) 固件 模型参数 打包 → 模型更新包 SHA-256 哈希 H = Hash(Package) 私钥签名 Sig = Sign(H, PrivKey) 传输通道 OTA / UART / SD (不可信) 包 + 签名 + 哈希 设备侧(MCU) 完整性验证 验签 + 比对哈希 公钥(烧录时预置) 关键流程说明: 1. 构建侧将固件与模型参数打包为更新包,计算 SHA-256 哈希值 H。 2. 使用私钥对 H 进行签名,生成签名值 Sig。更新包、H、Sig 三者共同传输。 3. 设备侧使用预置公钥验证 Sig 是否由对应私钥签发,再计算本地哈希与 H 比对。 4. 验签通过 + 哈希一致 → 更新包可信且完整;任一失败 → 拒绝更新。 注:哈希保证完整性(数据未被篡改),签名保证真实性(来源可信)。两者缺一不可。

上图展示了从构建到部署的完整信任链路。下面我们逐一拆解每个概念的本质、作用与工程实现要点。

2.1 固件与模型更新包:从“二进制”到“可交付单元”

固件(Firmware)是烧录在 MCU 非易失存储器(如 Flash)中的底层软件,负责硬件初始化、调度、外设驱动与运行时环境。在 TinyML 场景中,固件通常包含推理引擎(如 TensorFlow Lite Micro)、设备管理逻辑和引导加载程序(Bootloader)。固件的任何缺陷都可能导致设备变砖,因此其更新必须经过严格验证。

模型更新包(Model Update Package)则是一个更广义的概念——它不仅仅是模型权重文件,而是一个自包含的交付单元,通常包含以下内容:

  • 模型文件:量化后的 TFLite 或 ONNX 格式权重,可能经过压缩或加密。
  • 元数据:版本号、目标硬件平台、输入/输出张量形状、量化参数、兼容的固件版本范围。
  • 校验信息:哈希值、签名值、时间戳或防重放随机数(Nonce)。
  • 可选附加资源:标签映射文件、预处理配置、回调脚本等。

将固件与模型分开管理是 TinyML 的常见实践。固件更新频率低(数月一次),而模型更新频率高(每周甚至每天)。因此,模型更新包的设计应轻量化,避免携带完整固件,以减少传输带宽和 Flash 占用。

工程要点:模型更新包应设计为“差分”或“增量”格式。例如,仅更新模型文件的权重部分,而非整个固件镜像。这要求固件中预留模型存储分区(如独立的 Flash 区域),并通过引导加载程序支持分区切换(A/B 分区或乒乓升级)。

2.2 哈希(Hash):数据完整性的“指纹”

哈希函数(如 SHA-256)将任意长度的数据映射为固定长度的摘要(32 字节)。其核心特性包括:

  • 单向性:从哈希值无法反推原始数据。
  • 抗碰撞性:找到两个不同输入产生相同哈希值在计算上不可行。
  • 雪崩效应:输入数据微变,哈希值完全改变。

在更新包验证中,哈希用于检测传输错误或恶意篡改。设备端重新计算接收到的包哈希,与发送方提供的哈希比对。若不一致,则说明数据在传输过程中被修改或损坏。

常见误区:哈希只能证明“数据没变”,但不能证明“数据来自可信方”。攻击者可以同时替换更新包和哈希值。因此,哈希必须与签名配合使用——签名保护哈希本身,哈希保护数据内容。

2.3 签名(Signature):数据来源的“身份证明”

数字签名基于非对称加密(如 ECDSA、RSA)。签名过程如下:

  1. 发送方使用私钥对更新包的哈希值进行签名运算,生成签名值。
  2. 接收方使用公钥验证签名是否有效。

签名提供了两个关键保证:

  • 真实性(Authentication):只有持有私钥的合法发布者才能生成有效签名。
  • 不可否认性(Non-repudiation):发布者无法否认曾发布该更新包。

在 TinyML 设备中,公钥通常在出厂时烧录到设备的 OTP(一次性可编程)存储器或安全元件中。私钥则保存在云端签名服务器或离线 HSM(硬件安全模块)中,绝不进入设备。

经验提醒:对于资源受限的 MCU(如 Cortex-M0+),ECDSA P-256 签名验证比 RSA-2048 快约 10 倍,且密钥更短。推荐使用 ECDSA P-256 作为 TinyML 设备的默认签名算法。

2.4 完整性验证:从“信任根”到“应用加载”

完整性验证不是单一操作,而是一条信任链。设备启动时,引导加载程序(Bootloader)是第一个信任根。它验证固件镜像的签名,固件再验证模型更新包的签名。每一级验证都建立在前一级可信的基础上。

完整的验证流程通常包含以下步骤:

步骤 操作 输入 输出/决策
1 接收更新包 包 + 签名 + 哈希 暂存于 RAM 或临时分区
2 计算本地哈希 更新包数据 本地哈希 H'
3 验证签名 签名值 + 公钥 + 发送方哈希 H 签名有效 / 无效
4 比对哈希 H' 与 H 一致 / 不一致
5 版本与兼容性检查 元数据(版本号、固件版本范围) 允许更新 / 拒绝
6 写入目标分区 验证通过的更新包 更新 Flash 并触发重启

注意,步骤 3 和 4 的顺序不能颠倒。必须先验证签名(确认哈希 H 来自可信方),再比对哈希(确认数据与 H 一致)。如果先比对哈希,攻击者可以同时替换数据和哈希值。

2.5 案例拆解:一个智能传感器节点的模型更新失败排查

某工业 IoT 项目部署了 500 个基于 STM32L4 的振动传感器节点,通过 BLE 接收模型更新包。某次更新后,部分节点出现推理结果异常,但更新流程显示“成功”。

初始现象:约 12% 的节点在更新后输出错误分类结果,其余节点正常。更新日志显示所有节点均通过了签名验证和哈希比对。

关键输入数据:

  • 更新包大小:48,312 字节
  • SHA-256 哈希:a3f2...9c1d(前 4 字节与后 4 字节)
  • 签名算法:ECDSA P-256
  • 固件版本:v2.1.0(支持模型版本 ≥ 3.0)
  • 模型版本:v3.2(元数据中声明兼容固件 v2.1.0+)

分析判断过程:

  1. 签名验证通过,说明包确实来自官方私钥,排除恶意注入。
  2. 哈希比对通过,说明传输无损坏。
  3. 异常节点与正常节点的唯一区别是:异常节点的 Flash 剩余空间小于 4 KB,而正常节点均大于 8 KB。
  4. 进一步检查发现,异常节点在写入模型时,由于 Flash 空间不足,部分模型文件被截断,但截断发生在哈希计算之后——即设备先验证了完整包,再写入时因空间不足导致写入不完整。

实际操作步骤:

  1. 在固件中增加写入前空间检查:if (free_flash < package_size + 4KB) reject_update();
  2. 增加写入后回读校验:写入完成后,重新计算 Flash 中模型数据的哈希,与发送方哈希比对。
  3. 在元数据中增加 min_free_flash 字段,由构建工具自动计算并填充。

结果对比:修复后,连续 3 次更新(共 1500 节点次)均无异常,回读校验捕获了 2 次因 Flash 磨损导致的写入错误。

风险与代价:回读校验增加了约 200ms 的更新时间,但对于安全性要求高的工业场景可接受。空间检查避免了“验证通过但写入失败”的假成功状态。

复盘经验:完整性验证不能止步于“传输层”,必须延伸到“存储层”。哈希比对的是内存中的临时数据,而真正运行的是 Flash 中的持久数据。两者之间可能存在差异(写入截断、位翻转、磨损)。

2.6 常见误区与总结

误区 后果 正确做法
只做哈希校验,不做签名验证 攻击者可同时替换包和哈希值 签名 + 哈希双重验证
签名验证通过后跳过哈希比对 签名只保护哈希,不保护数据本身 验签后必须重新计算本地哈希并比对
将公钥存储在可写 Flash 中 攻击者可替换公钥,伪造任意签名 公钥烧录于 OTP 或安全元件
验证通过后立即写入,无回读校验 写入失败或截断导致运行异常 写入后回读哈希比对
忽略版本兼容性检查 新模型与旧固件不兼容,推理崩溃 元数据中声明兼容范围,设备端强制检查