密码学基础回顾:哈希算法、非对称加密与数字签名

各位同学好,我是你们的嵌入式安全讲师。今天咱们聊聊安全启动的基石——密码学。说实话,很多工程师一听到「密码学」三个字就头大,觉得那是数学家的事。但在我多年的固件开发经历中,真正用到的核心工具其实就三样:哈希、非对称加密、数字签名。搞懂这三样,安全启动的原理你就掌握了七成。

2.1 哈希算法:数据的「指纹」

哈希算法,说白了就是把任意长度的数据,压缩成一个固定长度的摘要。这个摘要就像人的指纹——理论上独一无二,而且无法从指纹反推出人的长相。

核心特性:

  • 单向性:从哈希值无法还原原始数据
  • 抗碰撞性:很难找到两个不同数据拥有相同哈希值
  • 雪崩效应:输入改一个比特,输出完全变样

我在项目中遇到过最典型的场景:固件升级包下载到设备后,先算一遍 SHA256,跟服务器下发的哈希值比对。不一样?直接拒绝启动。就这么简单粗暴。

SHA256 到底怎么算?

SHA256 输出固定 256 位,也就是 32 字节。你想想看,哪怕你传一个 1GB 的固件,最后也就这 32 字节的摘要。效率极高。

// 伪代码示例:计算固件哈希
uint8_t firmware_hash[32];
SHA256_CTX ctx;
sha256_init(&ctx);
sha256_update(&ctx, firmware_buffer, firmware_size);
sha256_final(&ctx, firmware_hash);

// 比对
if (memcmp(firmware_hash, expected_hash, 32) != 0) {
    // 固件被篡改,拒绝启动
    panic();
}

我的习惯:实际项目中,我会把哈希计算放在安全隔离区(如 TrustZone 或 HSM)里执行,防止攻击者在计算过程中篡改结果。嗯,这里要注意,哈希本身不防篡改,它只是「检测」篡改的工具。

2.2 非对称加密:公钥与私钥的默契

对称加密就像一把钥匙开一把锁,加密解密用同一个密钥。但问题来了——这把钥匙怎么安全地传给对方?非对称加密解决了这个难题。

非对称加密使用一对密钥:公钥公开分发,私钥秘密保存。公钥加密的数据只能用私钥解密,反之亦然。

特性 RSA ECC(椭圆曲线)
密钥长度 2048 / 4096 位 256 / 384 位
安全强度 高 高(同等长度下更强)
计算速度 慢(尤其私钥操作) 快
资源消耗 高 低
典型应用 传统安全启动、证书 IoT 设备、嵌入式系统

我个人习惯在资源受限的 MCU 上优先选 ECC。为什么?你想想看,一个 256 位的 ECC 密钥,安全强度相当于 3072 位的 RSA。省下的存储空间和计算时间,对嵌入式设备来说太宝贵了。

我曾经踩过的坑:有次做产品选型,用了某款 MCU 的硬件 RSA 加速器,结果发现它只支持 1024 位密钥。1024 位 RSA 在 2023 年以后已经被业界认定为不安全。那次差点导致项目返工。所以我的建议是:RSA 至少 2048 位,ECC 至少 256 位。

2.3 数字签名:谁签的?改没改?

数字签名解决两个问题:身份认证(是谁签的)和完整性(签完之后改没改)。

流程其实很简单:

  1. 签名方:对数据算哈希,然后用私钥加密这个哈希,得到签名
  2. 验证方:用公钥解密签名得到哈希值 H1,再自己算一遍数据的哈希值 H2
  3. 如果 H1 == H2,说明数据没被改,而且确实是私钥持有者签的

说白了,数字签名 = 哈希 + 非对称加密。没有哈希,直接加密整个固件?那效率太低了。先哈希再签名,是工程上的最优解。

// 签名过程(伪代码)
uint8_t signature[256];
uint8_t hash[32];

sha256(firmware, firmware_size, hash);
rsa_sign(private_key, hash, signature);  // 用私钥加密哈希

// 验证过程(伪代码)
uint8_t decrypted_hash[32];
uint8_t computed_hash[32];

rsa_verify(public_key, signature, decrypted_hash);  // 用公钥解密
sha256(firmware, firmware_size, computed_hash);

if (memcmp(decrypted_hash, computed_hash, 32) == 0) {
    // 验证通过
} else {
    // 签名无效
}

2.4 知识体系总览

下面这张图,是我自己画的知识框架。每次带新人时我都会先让他们看这个,把三者的关系理清楚。

密码学基础:安全启动核心知识体系 哈希算法 (SHA256) 非对称加密 (RSA/ECC) 数字签名 特性 • 单向性 • 抗碰撞性 • 雪崩效应 特性 • 公钥/私钥对 • 单向加密 • 密钥长度差异 特性 • 身份认证 • 完整性校验 • 不可否认性 应用场景:固件签名 → 安全启动 → 运行时完整性校验 安全启动流程 BootROM → 验证 Bootloader 签名 → 验证 OS 签名 → 验证应用签名

2.5 实际项目中的选择建议

讲完理论,咱们聊聊落地。我这些年经手过几十个嵌入式安全项目,总结了几条经验:

  • MCU 资源紧张(< 256KB Flash):用 ECC-256 + SHA256,硬件加速器能省则省
  • 性能要求高(启动时间 < 1秒):用硬件加速的 RSA-2048,或者 ECC 配合专用引擎
  • 需要兼容现有 PKI 体系:RSA-2048 是主流,证书链验证绕不开它
  • 极端安全要求(车规、金融):RSA-4096 或 ECC-384,配合独立 HSM

一个小技巧:我习惯在固件头部预留一个「签名信息区」,里面存签名算法标识、密钥索引、签名值。这样 Bootloader 读到头部就知道该用哪个算法验证,不用硬编码。灵活性高很多。