2、密码学基础回顾:对称加密与非对称加密、哈希函数特性、数字签名原理

各位同学好,我是老周。今天咱们聊点基础但绕不开的东西——密码学基础。你可能会说:“这些我早就会了。” 但说实话,我在固件安全这行干了十几年,见过太多因为基础不牢导致翻车的案例。所以咱们还是踏踏实实过一遍,尤其要搞清楚:这些东西跟固件签名验签到底有什么关系。

2.1 对称加密:快,但有个大麻烦

对称加密,说白了就是加密和解密用同一把钥匙。你拿钥匙锁门,拿同一把钥匙开门。典型算法有 AES、DES、SM4(国密)。

核心特点:

  • 速度快:硬件加速后,AES-128 能做到每秒几十 GB 的吞吐量。适合加密固件本身。
  • 密钥分发难:这是硬伤。你想想看,如果我要给一万台设备更新固件,怎么把密钥安全地送到每台设备里?

我在项目中遇到过:某次做 IoT 网关,工程师直接用硬编码的 AES 密钥加密固件。结果固件被提取后,密钥直接暴露在二进制里。嗯,那批设备后来全部召回重刷。教训就是:对称加密不适合做固件签名验签的根信任。

特性 对称加密 在固件保护中的角色
密钥管理 双方共享同一密钥 分发困难,易泄露
性能 极高(硬件加速) 适合加密固件负载
典型算法 AES-128/256, SM4 用于固件内容加密(非签名)
抗量子 弱(Grover 算法减半安全强度) 需关注后量子迁移

2.2 非对称加密:慢,但解决了信任问题

非对称加密,就是一对钥匙:公钥和私钥。公钥可以公开,私钥必须保密。你用私钥签名,别人用公钥验证。反过来,别人用公钥加密,只有你能用私钥解密。

为什么固件签名必须用非对称?

  • 私钥只保存在厂商手里,设备里只放公钥。
  • 公钥被提取了也没事——它只能验签,不能伪造签名。
  • 这就是信任链的根。

我个人习惯:在固件签名流程中,先用哈希摘要固件,再用私钥加密摘要。这样既利用了非对称的安全性,又避免了直接加密大固件的性能开销。后面会细讲。

特性 非对称加密 在固件保护中的角色
密钥管理 公钥公开,私钥保密 公钥可嵌入设备,私钥离线保存
性能 慢(比对称慢 100-1000 倍) 只签名摘要,不签名全文
典型算法 RSA-2048/4096, ECDSA, SM2 固件签名/验签的核心
抗量子 RSA/ECDSA 脆弱,SM2 同样脆弱 需关注 CRYSTALS-Dilithium 等

2.3 哈希函数:固件的“指纹”

哈希函数,就是把任意长度的数据,压缩成固定长度的摘要。比如 SHA-256 输出 256 位,SM3 输出 256 位。

哈希函数必须满足三个特性:

  1. 抗原像性:给定摘要,无法反推出原文。说白了就是不可逆。
  2. 抗第二原像性:给定原文和摘要,找不到另一个原文产生相同摘要。
  3. 抗碰撞性:找不到任意两个不同的原文,产生相同摘要。

我曾经踩过一个坑:某项目用了 MD5 做固件完整性校验。结果攻击者构造了两个不同的固件版本,MD5 摘要完全一样。设备升级了恶意固件,但校验通过了。从那以后,我规定所有项目最低用 SHA-256,国密场景用 SM3。

在固件签名中的角色:

  • 对固件全文做哈希,得到摘要。
  • 对摘要签名,而不是对固件全文签名。
  • 验签时,重新计算固件哈希,再验证签名。

2.4 数字签名原理:签名与验签的完整流程

好了,前面三个概念都铺垫完了。现在咱们把它们串起来,看看数字签名到底怎么工作。

签名过程(厂商侧):

  1. 计算固件哈希:digest = SHA256(firmware.bin)
  2. 用私钥签名摘要:signature = RSA_sign(private_key, digest)
  3. 打包固件 + 签名 + 公钥证书:firmware_package = firmware.bin || signature || cert

验签过程(设备侧):

  1. 解包得到固件、签名、公钥。
  2. 计算固件哈希:digest' = SHA256(firmware.bin)
  3. 用公钥验签:result = RSA_verify(public_key, digest', signature)
  4. 如果 result 为真,固件可信;否则拒绝升级。

核心逻辑:哈希保证了固件内容的完整性,非对称签名保证了固件来源的真实性。两者缺一不可。

// 伪代码示例:固件签名与验签
// 签名侧(厂商)
uint8_t firmware[FIRMWARE_SIZE];
uint8_t digest[32];  // SHA-256 输出
SHA256(firmware, sizeof(firmware), digest);

uint8_t signature[256]; // RSA-2048 签名
RSA_sign(private_key, digest, sizeof(digest), signature);

// 验签侧(设备)
uint8_t digest_prime[32];
SHA256(firmware, sizeof(firmware), digest_prime);

bool valid = RSA_verify(public_key, digest_prime, sizeof(digest_prime), signature);
if (valid) {
    // 固件可信,执行升级
} else {
    // 拒绝升级,记录日志
}

2.5 知识体系总览

下面这张图,把本章的核心逻辑串起来了。你可以看到:哈希函数、对称加密、非对称加密,各自在固件保护中扮演什么角色。

固件保护密码学基础体系 固件保护密码学基础体系 对称加密 非对称加密 哈希函数 特性 • 速度快,适合加密负载 • 密钥分发困难 • 典型:AES, SM4 特性 • 公钥公开,私钥保密 • 速度慢,只签摘要 • 典型:RSA, ECDSA, SM2 特性 • 不可逆,固定长度 • 抗碰撞,抗原像 • 典型:SHA-256, SM3 角色:加密固件内容 (配合密钥管理) 角色:签名/验签核心 (信任根) 角色:完整性校验 (指纹) 数字签名 = 哈希 + 非对称加密

2.6 避坑指南:我见过的常见错误

做固件签名这么多年,有些坑真的是反复出现。我列几个最常见的,你以后遇到了能少走弯路。

  • 直接用对称密钥签名:有人觉得 AES 快,就用 AES 加密当签名。但对称密钥没有非对称的“公钥可公开”特性,设备里存密钥等于把信任根暴露了。
  • 哈希算法选太弱:MD5、SHA-1 已经可以被碰撞攻击。我见过某厂商用 SHA-1 签固件,结果被构造了碰撞固件,直接绕过验签。
  • 签名摘要长度不足:RSA-1024 已经被认为不够安全。我个人建议最低 RSA-2048 或 ECDSA P-256,国密场景用 SM2。
  • 公钥硬编码且不校验:设备里的公钥如果被替换,攻击者可以用自己的私钥签名恶意固件。所以公钥本身也要有保护机制(比如 OTP 或安全存储)。

我的建议:如果你刚开始做固件签名,直接选 ECDSA P-256 + SHA-256 组合。性能好,安全性够,生态成熟。国密场景用 SM2 + SM3。别自己造轮子,用现成的库(OpenSSL、mbedTLS、国产的 GmSSL)。

好了,这一章就到这里。密码学基础是固件保护的根基,后面所有章节都会用到这些概念。你把这些搞清楚了,后面的签名验签流程、证书链、安全启动,学起来会轻松很多。