4、密码学基础:哈希算法(SHA-256)、非对称加密(RSA/ECC)、数字签名、密钥管理基础

Secure Boot 的信任根建立与链式校验机制,本质上是一套精心设计的密码学协议。在 MCU 资源受限的背景下,理解哈希、非对称加密、数字签名与密钥管理的数学原理和工程约束,是进行移植与配置的前提。本章将聚焦这四大核心模块,从算法本质到 MCU 上的工程落地,建立完整的密码学知识框架。

Secure Boot 密码学基础架构 SHA-256 哈希 完整性校验 固定256位输出 RSA / ECC 公钥加密 / 私钥签名 密钥对生成与分发 数字签名 防伪造 + 防篡改 签名生成与验证 密钥管理 OTP / eFuse 存储 密钥轮换与撤销 信任根 (Root of Trust) 不可变引导代码 公钥哈希锁定 安全启动流程 逐级验证固件 签名校验 + 哈希比对 核心链路:信任根 → 密钥管理 → 签名验证 → 固件加载 SHA-256 提供完整性,RSA/ECC 提供真实性,密钥管理保护信任根

4.1 哈希算法 SHA-256:完整性校验的基石

4.1.1 核心原理与数学特性

SHA-256(Secure Hash Algorithm 256-bit)是 SHA-2 家族的一员,由美国国家安全局(NSA)设计,并于 2001 年由 NIST 发布为 FIPS PUB 180-4 标准。它将任意长度的输入消息,经过填充、分块、压缩函数迭代等步骤,输出固定 256 位(32 字节)的摘要值。其核心安全属性包括:

  • 抗原像性(Preimage Resistance):给定摘要值 y,找到满足 H(x)=y 的输入 x 在计算上不可行。这意味着攻击者无法从哈希值反推出原始固件内容。
  • 抗第二原像性(Second Preimage Resistance):给定输入 x₁,找到另一个输入 x₂(x₁≠x₂)使得 H(x₁)=H(x₂) 在计算上不可行。这防止攻击者用恶意固件替换合法固件而不改变哈希值。
  • 抗碰撞性(Collision Resistance):找到任意两个不同的输入 x₁ 和 x₂ 使得 H(x₁)=H(x₂) 在计算上不可行。虽然理论上存在碰撞,但 SHA-256 的碰撞复杂度为 2^128,在当前算力下不可实现。

在 MCU 的 Secure Boot 场景中,SHA-256 主要用于两个关键环节:一是对固件镜像进行哈希计算,生成摘要值用于签名;二是在启动时重新计算固件哈希,与解密后的摘要值进行比对,以验证固件在传输或存储过程中是否被篡改。

工程要点:SHA-256 是单向函数,不可逆。在 Secure Boot 中,它不提供机密性保护,只提供完整性校验。如果固件被加密存储,哈希计算应在解密之后进行,否则校验的是密文的完整性而非明文。

4.1.2 MCU 上的实现方式与性能考量

在资源受限的 MCU 上实现 SHA-256,通常有三种途径:

实现方式典型吞吐量代码/资源占用适用场景
纯软件实现(C语言)5-20 MB/s(Cortex-M4 @ 100MHz)约 2-4 KB Flash,256B RAM低成本 MCU,无硬件加速器
硬件加速器(SHA Engine)50-200 MB/s寄存器配置,DMA 支持中高端 MCU(如 STM32L5、NXP i.MX RT)
指令集加速(如 ARMv8-M SHA 扩展)30-80 MB/s专用指令,减少循环开销ARMv8-M 架构 MCU

对于 1MB 的固件镜像,纯软件实现大约需要 50-200ms(取决于主频),而硬件加速器可将时间缩短至 5-20ms。在启动时间敏感的工业控制或汽车电子场景中,硬件加速几乎是必须的。

4.1.3 实战场景:固件完整性校验流程

假设我们使用 STM32L552(Cortex-M33,带硬件 SHA-256 加速器)进行 Secure Boot 设计。启动流程中的哈希校验环节如下:

  1. BootROM 从固定地址读取固件头部信息,获取固件长度、版本号、签名偏移量等元数据。
  2. 配置 SHA 硬件外设,设置输入数据源为 Flash 中的固件区域,输出为 32 字节摘要。
  3. 启动 DMA 传输,将固件数据流式送入 SHA 引擎,避免 CPU 逐字节搬运。
  4. 计算完成后,将硬件生成的摘要与固件头中存储的参考摘要进行常量时间比较(防止时序攻击)。
  5. 若匹配,则继续执行签名验证;若不匹配,则进入错误处理流程(如 LED 指示、进入恢复模式)。
常见误区:不要使用 memcmp() 进行摘要比对,因为它在遇到第一个不匹配字节时就会返回,攻击者可通过测量响应时间推断出正确前缀。应使用专用的安全比较函数,如 CRYPTO_memcmp 或逐字节异或累积后判断结果。

4.2 非对称加密:RSA 与 ECC 的工程选型

4.2.1 RSA 算法原理与参数选择

RSA 的安全性基于大整数分解的困难性。其密钥生成过程为:选择两个大素数 p 和 q,计算 n=p×q,选取公钥指数 e(通常为 65537),计算私钥 d 满足 e×d ≡ 1 (mod φ(n))。公钥为 (n, e),私钥为 (n, d)。

在 MCU 上使用 RSA 进行签名验证时,通常采用 RSA2048 或 RSA3072。RSA2048 的模数长度为 2048 位(256 字节),签名验证需要进行一次模幂运算,即计算 m^e mod n。虽然公钥指数 e=65537 只有 17 位,但模幂运算仍需要约 300-500ms(Cortex-M4 @ 100MHz,无硬件加速)。

RSA 的优点是算法成熟、实现简单、公钥短小(256 字节),适合在资源极受限的 BootROM 中硬编码公钥。缺点是签名验证速度慢,且密钥生成需要大素数筛选,不适合在 MCU 上动态生成密钥对。

4.2.2 ECC 算法原理与曲线选择

椭圆曲线密码学(ECC)的安全性基于椭圆曲线离散对数问题(ECDLP)。在相同的安全强度下,ECC 的密钥长度远短于 RSA。例如,256 位 ECC(如 secp256r1/P-256)提供与 3072 位 RSA 相当的安全性。

ECC 的签名算法通常使用 ECDSA(Elliptic Curve Digital Signature Algorithm)。签名过程涉及标量乘法 k×G,验证过程涉及两个标量乘法。在 MCU 上,P-256 曲线的签名验证时间约为 50-150ms(Cortex-M4 @ 100MHz),比 RSA2048 快 3-5 倍。

ECC 的工程挑战在于:

  • 侧信道防护:标量乘法需要采用固定时间算法(如 Montgomery Ladder),防止通过功耗分析提取私钥。
  • 曲线参数验证:验证公钥时需检查点是否在曲线上,防止无效曲线攻击。
  • 随机数质量:ECDSA 要求每次签名使用唯一的随机数 k,若 k 泄露或重复,私钥可被直接恢复。
选型建议:对于 MCU Secure Boot,如果 BootROM 空间极其有限(<8KB),且对启动时间要求不高,可选择 RSA2048 + 公钥硬编码。如果对启动时间敏感(如汽车 ECU 要求 <100ms),或需要支持密钥轮换,优先选择 ECC P-256。

4.2.3 案例拆解:RSA vs ECC 在车规 MCU 上的对比

某车规级 MCU(Cortex-R5F @ 200MHz)需要实现 Secure Boot,固件大小为 2MB,启动时间预算为 200ms。我们对比两种方案:

指标RSA2048ECC P-256
签名验证时间约 180ms约 45ms
SHA-256 计算时间(2MB)约 20ms(硬件加速)约 20ms(硬件加速)
公钥存储空间256 字节64 字节(x 坐标 + y 坐标)
总启动时间约 200ms(临界)约 65ms(充裕)
代码复杂度低(模幂运算)中(标量乘法 + 点运算)

从结果看,ECC 在启动时间上具有明显优势,但需要更复杂的代码实现和更严格的侧信道防护。最终该方案选择了 ECC P-256,并配合硬件加密协处理器(支持 ECC 点运算)将验证时间进一步压缩至 15ms。

4.3 数字签名:从理论到固件验证

4.3.1 签名生成与验证的完整流程

数字签名结合了哈希算法和非对称加密,提供真实性、完整性和不可否认性。在 Secure Boot 场景中,签名由开发服务器(离线)生成,验证在 MCU 上执行。流程如下:

  1. 签名生成(开发环境):计算固件镜像的 SHA-256 摘要 H(m);使用私钥对摘要进行签名,得到签名值 S = Sign_priv(H(m));将 S 附加到固件镜像中,生成带签名的固件包。
  2. 签名验证(MCU 启动):读取固件镜像,计算 SHA-256 摘要 H'(m);使用公钥验证签名,即验证 Verify_pub(S, H'(m)) 是否通过;若通过,则固件未被篡改且来源可信。

对于 RSA,签名验证实质上是计算 S^e mod n,并与 H'(m) 比较。对于 ECDSA,验证涉及计算 u₁×G + u₂×Q(其中 Q 为公钥点),并比较结果点的 x 坐标与签名中的 r 值。

4.3.2 签名方案的安全增强:哈希截断与填充

在实际工程中,直接对摘要进行签名存在理论风险(如长度扩展攻击)。因此,标准方案使用 RSA-PSS(Probabilistic Signature Scheme)或 ECDSA 的标准流程。RSA-PSS 引入了随机盐值,使得相同消息在不同签名下产生不同签名值,增强了安全性。在 MCU 上实现时,需要注意:

  • RSA-PSS 需要额外的编码/解码逻辑,代码量增加约 1-2KB。
  • ECDSA 的签名值由 (r, s) 两个 32 字节整数组成,共 64 字节,比 RSA2048 的 256 字节签名短得多。
  • 验证时需检查签名值是否在有效范围内(如 r, s ∈ [1, n-1]),防止伪造签名。
安全提示:在 MCU 上验证签名时,必须使用公钥对应的算法标识(如 OID)进行匹配。如果固件头中声明使用 RSA-PSS,但 BootROM 只实现了 PKCS#1 v1.5,应直接拒绝加载,而不是尝试兼容。

4.3.3 实战场景:多级签名链的验证顺序

在复杂的 Secure Boot 架构中,通常存在多级引导:BootROM → 一级引导加载器(SPL)→ 主固件。每一级都需要验证下一级的签名。签名链如下:

BootROM (信任根)
  └─ 验证 SPL 的签名 (使用 SPL 公钥)
       └─ SPL 验证主固件的签名 (使用主固件公钥)
            └─ 主固件运行

这种链式验证的优点是:即使主固件被攻破,攻击者也无法伪造 SPL,因为 SPL 的签名由 BootROM 中的根公钥验证。但需要注意:

  • 每一级验证都会增加启动时间,需合理分配各级的算法选择(如 BootROM 使用 ECC,SPL 使用 RSA)。
  • 公钥的存储位置应逐级隔离:根公钥存储在 OTP/eFuse 中,SPL 公钥存储在 SPL 固件中,主固件公钥存储在主固件头中。
  • 如果某一级验证失败,应进入安全恢复模式,而不是继续执行。

4.4 密钥管理基础:信任根的建立与保护

4.4.1 密钥生命周期与存储介质

密钥管理是 Secure Boot 安全性的最终保障。即使算法再强,如果私钥泄露或公钥被替换,整个信任链将崩溃。密钥生命周期包括:生成、分发、存储、使用、轮换、撤销、销毁。

在 MCU 上,密钥存储介质的选择至关重要:

存储介质容量可写性安全性典型用途
OTP (One-Time Programmable)1-8 KB仅一次写入高(物理不可复制)根公钥哈希、设备唯一密钥
eFuse1-4 KB可多次烧写(有限次)高安全启动配置、密钥版本号
Flash 安全区域16-64 KB可擦写中(依赖 Flash 保护)应用固件密钥、更新密钥
外部安全芯片(如 ATECC608)16 KB硬件保护极高高安全场景的密钥托管

根公钥通常以哈希值形式存储在 OTP 中。BootROM 在启动时计算待加载公钥的 SHA-256,与 OTP 中的哈希比对,若匹配则信任该公钥。这种方式允许公钥存储在 Flash 中(便于更新),但哈希值锁定在 OTP 中,防止攻击者替换公钥。

4.4.2 密钥轮换与版本回滚防护

密钥轮换是应对密钥泄露或算法弱化的必要手段。在 Secure Boot 中,密钥轮换需要谨慎设计,因为一旦新密钥不被旧 BootROM 信任,设备将变砖。常见的策略包括:

  • 密钥版本号:在固件头中增加密钥版本字段,BootROM 比较版本号,只允许加载版本号 ≥ 当前版本的固件。
  • 密钥撤销列表:在 OTP 中维护已撤销的密钥 ID 列表,BootROM 在验证前检查。
  • 双密钥槽位:预留两个密钥槽位,当前密钥验证失败时尝试备用密钥,实现无缝切换。
风险提示:密钥轮换时,必须确保新公钥的哈希已烧写进 OTP。如果 OTP 空间不足,可采用“哈希链”方式:OTP 中存储根哈希,根哈希对应一个中间公钥,中间公钥再签发新的公钥。但这种方式增加了验证层级和代码复杂度。

4.4.3 案例拆解:基于 eFuse 的密钥管理方案

某物联网 MCU 产品需要支持远程固件更新,同时防止攻击者回滚到旧版本固件(利用已知漏洞)。设计方案如下:

  1. 初始烧录:在工厂烧录时,将根公钥哈希(32 字节)写入 eFuse 区域 0,将密钥版本号初始化为 1。
  2. 固件更新:新固件使用新私钥签名,固件头中包含密钥版本号 2。BootROM 验证签名前,先检查版本号 ≥ eFuse 中的当前版本。
  3. 版本升级:验证通过后,BootROM 将 eFuse 中的版本号更新为 2。此时旧固件(版本号 1)将无法通过版本检查。
  4. 密钥轮换:当需要更换密钥时,新公钥的哈希写入 eFuse 区域 1,同时将版本号递增。BootROM 优先使用区域 1 的公钥,若验证失败则回退到区域 0。

该方案的代价是 eFuse 空间占用(2×32 字节 + 版本号),以及每次更新需要烧写 eFuse 的时间(约 10ms)。但换取了防回滚和密钥轮换能力,适用于安全要求较高的产品。

4.4.4 常见误区与总结复盘

在密钥管理实践中,以下误区需要特别注意:

  • 私钥存储在 MCU 中:Secure Boot 只需要公钥验证签名,私钥应始终保存在开发服务器或 HSM 中。如果 MCU 中存储了私钥,攻击者可通过调试接口提取。
  • 忽略调试接口保护:即使 Secure Boot 验证通过,如果 JTAG/SWD 接口未锁定,攻击者仍可读取 Flash 内容或篡改内存。必须同时启用调试接口保护(如 RDP Level 2)。
  • 随机数生成器质量不足:ECDSA 签名需要高质量随机数。如果 MCU 的 TRNG 未正确初始化或熵源不足,可能导致签名密钥泄露。建议使用硬件 TRNG + 软件去偏。
  • 忽视侧信道攻击:在验证签名时,如果模幂运算或标量乘法的时间依赖于密钥或消息,攻击者可通过功耗分析提取信息。应使用固定时间算法或硬件加速器。
总结:密码学基础是 Secure Boot 的基石。SHA-256 提供完整性,RSA/ECC 提供真实性,数字签名将两者结合,密钥管理则确保信任根不被破坏。在 MCU 移植时,应根据资源、启动时间和安全等级,综合选择算法组合与密钥存储方案。建议在项目初期就完成威胁建模,明确需要防御的攻击类型(如固件提取、回滚、伪造),再针对性地设计密码学方案。