2. 密码学基础回顾

各位同学,咱们正式开始之前,我得先问一句:你手头的 IoT 设备,现在还在用 RSA-2048 或者 ECDSA 签名吗?如果是,那你今天这堂课算是来对了。

这一章,咱们不急着讲 PQC 怎么迁移。先把老本行——公钥密码、哈希函数、数字签名——彻底捋一遍。我做了十几年固件安全,见过太多因为“基础不牢”导致的签名漏洞。说白了,签名这事儿,原理上就三步:哈希摘要 → 私钥加密 → 公钥验证。但每一步都有坑。

2.1 公钥密码体系:为什么我们需要两把钥匙?

对称加密,就像你和老婆共用一把家门钥匙。你锁门,她开门,方便。但问题是:这把钥匙怎么给她?邮寄?快递员偷看了怎么办?

公钥密码解决了这个世纪难题。它给你两把钥匙:

  • 公钥:公开的,谁都可以拿。就像你的门牌号,全世界都知道。
  • 私钥:私密的,只有你自己有。就像你家的保险柜钥匙,丢了就完了。

这两把钥匙在数学上是配对的。用公钥加密的数据,只有对应的私钥能解开。反过来,用私钥签名的数据,只有对应的公钥能验证。

核心概念:公钥加密 ≠ 数字签名。虽然都用同一对密钥,但用途完全相反。

  • 加密:公钥加密 → 私钥解密(保证机密性)
  • 签名:私钥签名 → 公钥验证(保证完整性和真实性)

我在一个智能门锁项目里遇到过这样的问题:工程师把签名用的私钥直接硬编码在固件里,结果固件被反编译后,私钥泄露,攻击者可以伪造任何固件更新。嗯,那款门锁后来被召回重新设计了。

2.2 哈希函数:数字指纹的“压缩器”

你想想看,如果让你直接对 10MB 的固件镜像做 RSA 签名,那得算到猴年马月去?RSA 签名算法本身对输入长度有限制,而且效率极低。

哈希函数就是来解决这个问题的。它能把任意长度的数据,压缩成一个固定长度的“摘要”(比如 SHA-256 输出 32 字节)。这个摘要就像人的指纹,数据变了,指纹一定变。

一个好的哈希函数,必须满足三个特性:

  1. 抗原像性:给你摘要,你算不出原始数据。这叫“单向性”。
  2. 抗第二原像性:给你原始数据,你找不到另一个数据,哈希值相同。这叫“抗碰撞”。
  3. 抗碰撞性:你找不到任意两个不同的数据,哈希值相同。这是最严格的。

⚠️ 避坑指南:我曾经在 2017 年审计过一个 OTA 升级方案,他们还在用 SHA-1 做固件哈希。SHA-1 已经被 Google 和 CWI 研究所攻破了碰撞攻击。虽然实际攻击成本很高,但在 IoT 设备上,攻击者完全可以伪造一个哈希值相同的恶意固件。所以,现在至少要用 SHA-256。

常见的哈希函数对比:

算法 输出长度 安全状态 IoT 适用性
MD5 128 bit 已攻破(碰撞攻击) ❌ 不推荐
SHA-1 160 bit 已攻破(理论碰撞) ❌ 不推荐
SHA-256 256 bit 安全(截至 2025) ✅ 推荐
SHA-3 可变 安全 ✅ 推荐(但生态不如 SHA-2)

2.3 数字签名原理:签名与验签流程

好了,把公钥密码和哈希函数结合起来,就是数字签名。我习惯把签名流程画成一张图,这样团队里的硬件工程师也能看懂。

数字签名与验签流程 固件镜像 (Firmware) SHA-256 哈希 摘要 (Digest) 私钥签名 (RSA/ECDSA) 签名值 (Signature) 固件 + 签名值 → 传输 接收固件 SHA-256 哈希 摘要1 (Digest1) 公钥验签 摘要2 (Digest2) 比较 Digest1 == Digest2 ✅ 验签通过 / ❌ 拒绝 关键点 签名方:私钥签名摘要 验签方:公钥验证摘要

流程其实很简单,我拆成两步说:

2.3.1 签名流程(在开发机上执行)

  1. 计算哈希:对固件镜像计算 SHA-256 哈希,得到 32 字节的摘要。
  2. 私钥签名:用开发者的私钥(比如 RSA-2048 私钥)对摘要进行签名运算,生成签名值。
  3. 打包发布:将固件镜像 + 签名值 + 公钥证书打包在一起,发布给设备。

💡 个人习惯:我建议在签名前,先把固件镜像的哈希值打印出来,人工核对一遍。有一次我在 CI/CD 流水线里发现,因为脚本错误,签名工具对的是旧版本的固件做了签名,而发布的却是新版本。哈希核对帮我提前发现了这个 bug。

2.3.2 验签流程(在 IoT 设备上执行)

  1. 接收数据:设备收到固件镜像 + 签名值 + 公钥证书。
  2. 计算哈希:设备对收到的固件镜像计算 SHA-256 哈希,得到摘要1。
  3. 公钥验签:用预置在设备中的公钥(或从证书中提取的公钥)对签名值进行验签运算,得到摘要2。
  4. 比较摘要:如果摘要1 == 摘要2,验签通过,固件是合法的。否则,拒绝升级。

⚠️ 我曾经踩过的坑:公钥的存储位置。很多 IoT 设备把公钥放在文件系统里,攻击者可以通过文件读取漏洞替换公钥,然后用自己的私钥签名恶意固件。正确的做法是:将公钥烧录在一次性可编程存储器(OTP)或安全元件(SE)中,并且由 BootROM 在启动早期验证公钥的完整性。

2.4 为什么这套体系在 IoT 上开始“吃力”了?

你想想看,RSA-2048 和 ECDSA 在理论上还是安全的。但问题是:

  • 量子计算威胁:Shor 算法可以在多项式时间内分解大整数和计算离散对数。一旦量子计算机成熟,RSA 和 ECDSA 将瞬间被攻破。
  • IoT 设备的生命周期长:一个智能电表可能要在现场运行 10-15 年。你现在用 RSA-2048 签名,10 年后量子计算机可能已经能破解了。到时候,所有设备都得召回。
  • 签名长度和计算开销:RSA-4096 的签名值有 512 字节,对于低功耗蓝牙(BLE)传输来说,太长了。ECDSA 虽然短,但验签计算量在低端 MCU 上仍然不小。

所以,迁移到 PQC 不是“要不要”的问题,而是“什么时候”的问题。我个人建议,新设计的 IoT 产品,现在就应该预留 PQC 的算法接口,比如在 BootROM 中支持算法切换,或者在固件更新协议中预留扩展字段。