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

各位同学,咱们今天聊点硬核的。在正式进入安全启动的细节之前,我建议咱们先把密码学这块地基夯实了。你想想看,签名验签说白了就是密码学在固件安全上的一个具体应用。如果基础概念没吃透,后面看代码和流程的时候很容易懵。

我个人习惯把密码学工具分成三类:加密算法、哈希函数、数字签名。这三兄弟各司其职,但又在安全启动里紧密配合。咱们一个一个来过。

2.1 对称加密与非对称加密

先说加密。加密的目的很简单——让不该看的人看不懂。但怎么实现这个目的,有两种截然不同的思路。

2.1.1 对称加密:一把钥匙开一把锁

对称加密,顾名思义,加密和解密用的是同一把密钥。就像你家的门锁,出门用钥匙锁上,回家用同一把钥匙打开。

我在项目中用过 AES(高级加密标准),这是目前最主流的对称加密算法。它的特点是快,非常快。硬件加速器加持下,AES-128 加密一个 16 字节的数据块只需要几个时钟周期。

核心特性:

  • 密钥长度:AES-128、AES-192、AES-256,位数越高越安全,但速度略慢
  • 工作模式:ECB(不推荐)、CBC(常用)、CTR(适合并行)、GCM(带认证)
  • 典型应用:固件加密存储、通信信道加密

我曾经踩过一个坑:用 ECB 模式加密固件镜像。结果发现同样的明文块会产生同样的密文块,攻击者通过模式分析就能猜出固件结构。后来全部改成了 CBC 或 GCM 模式。记住:生产环境永远不要用 ECB。

2.1.2 非对称加密:公钥私钥各司其职

非对称加密就更有意思了。它有一对密钥:公钥可以公开,私钥必须保密。用公钥加密的数据只能用私钥解密,反过来,用私钥加密的数据只能用公钥解密。

你想想看,这解决了什么问题?对称加密最大的痛点就是密钥分发——你怎么安全地把密钥告诉对方?非对称加密直接绕过了这个问题:你把公钥扔到网上,谁都可以用它加密数据发给你,只有你能用私钥解密。

特性 对称加密 非对称加密
密钥数量 1 个(共享密钥) 2 个(公钥 + 私钥)
计算速度 快(硬件加速可达 Gbps) 慢(RSA-2048 签名约 1ms)
密钥分发 困难(需要安全信道) 容易(公钥可公开)
典型算法 AES, DES, SM4 RSA, ECC, SM2
安全启动角色 固件加密存储 签名验签

实际项目中,我们很少只用一种加密。我记得有个项目需要安全传输固件更新包,方案是:用 RSA 公钥加密一个临时生成的 AES 密钥,再用这个 AES 密钥加密固件本身。这就是典型的混合加密——既利用了非对称加密的密钥分发优势,又保留了对称加密的高性能。

2.2 哈希函数特性

哈希函数,也叫散列函数。它的输入可以是任意长度的数据,输出是一个固定长度的摘要(digest)。

我经常跟新同事说:哈希函数不是加密,它没有密钥,也不可逆。你没法从哈希值反推出原始数据。这一点非常重要。

2.2.1 哈希函数的三大特性

  • 抗原像性:给定哈希值 H,无法找到任何消息 M 使得 Hash(M) = H。说白了就是不可逆。
  • 抗第二原像性:给定消息 M1,无法找到另一个消息 M2 使得 Hash(M1) = Hash(M2)。防止伪造。
  • 抗碰撞性:无法找到任意两个不同的消息 M1 和 M2 使得它们的哈希值相同。

我建议你记住这个比喻:哈希函数就像一台碎纸机。你把文件放进去,出来一堆纸屑。你没法从纸屑还原文件,但你可以把另一份文件也放进去,看出来的纸屑是否完全一样。如果一样,说明两份文件相同。

2.2.2 常用哈希算法

算法 输出长度 安全性 备注
MD5 128 位 已破解 不要用于安全场景
SHA-1 160 位 已破解 2020 年后禁止使用
SHA-256 256 位 安全 安全启动首选
SHA-384 384 位 安全 更高安全等级
SM3 256 位 安全 国密标准

在安全启动中,哈希函数的作用是完整性校验。我们计算固件的哈希值,然后把这个哈希值保护起来。启动时重新计算哈希值,对比是否一致。如果固件被篡改,哪怕只改了一个比特,哈希值也会完全不同。

2.3 数字签名原理

好,现在我们把前面两样工具组合起来。数字签名 = 哈希函数 + 非对称加密。

为什么要组合?直接对固件做非对称加密不行吗?行,但太慢了。固件动辄几兆字节,RSA 加密一个字节都要几十微秒,加密整个固件得等到天荒地老。所以我们的做法是:先对固件取哈希,得到一个固定长度的摘要(比如 32 字节),然后只对这个摘要做签名。

2.3.1 签名与验签流程

我画了一张图,把整个流程串起来。你一看就明白了。

数字签名与验签流程 签名方(固件发布者) 原始固件 计算哈希值 H = SHA-256(固件) 用私钥签名 S = RSA_sign(H, PrivKey) 发布:固件 + 签名 S + 公钥 传输/存储 验签方(设备启动时) 收到:固件 + 签名 S + 公钥 计算哈希值 H' = SHA-256(固件) 用公钥解密签名 H'' = RSA_verify(S, PubKey) 对比 H' == H''? 匹配 → 启动固件 不匹配 → 拒绝启动 核心要点 签名 = 对哈希值做非对称加密;验签 = 解密后对比哈希值

2.3.2 为什么哈希函数不可或缺?

你可能会问:能不能直接对固件做签名,省掉哈希这一步?

理论上可以,但实际没人这么干。原因有两个:

  1. 性能:非对称签名算法对输入长度敏感。RSA-2048 签名一个 32 字节的哈希值只需要几毫秒,但签名一个 4MB 的固件可能需要几十秒。设备启动时等不起。
  2. 安全性:直接对固件签名,相当于把整个固件暴露在签名算法下。某些签名算法对特定格式的数据有弱点,哈希函数相当于一个"数据压缩器",把任意格式的数据统一成固定长度的摘要,消除了这些风险。

我建议你记住这个公式:数字签名 = 哈希 + 非对称加密。这是安全启动的基石。后面讲代码实现时,你会发现所有操作都是围绕这个公式展开的。

2.4 本章小结

咱们把今天的内容捋一遍:

  • 对称加密:快,但密钥分发困难。适合加密大量数据。
  • 非对称加密:慢,但密钥管理方便。适合签名和密钥交换。
  • 哈希函数:不可逆,固定输出。用于完整性校验。
  • 数字签名:哈希 + 非对称加密。既保证了完整性,又提供了真实性认证。