2. 密码学基础(上):哈希函数、数字签名与PKI
各位同学,欢迎来到密码学基础的上半部分。说实话,这部分内容看着有点枯燥,一堆数学公式和算法名字。但我要告诉你,这是整个安全启动的基石。你后面遇到的每一个安全机制,都离不开今天讲的这三个东西。
我个人习惯把这三者比作一个「信任三角」:哈希函数负责「验明正身」,数字签名负责「盖章确认」,PKI 负责「发身份证」。咱们一个一个来拆解。
2.1 哈希函数:数据的「指纹」
哈希函数,说白了就是一个「压缩器」。你给它任意长度的数据,它吐出一个固定长度的摘要。这个摘要,就是数据的「指纹」。
为什么需要它?你想想看,一个固件可能有几十兆字节。你要验证它的完整性,总不能每次都把整个固件传一遍吧?太慢了。我们只需要验证它的哈希值就行。
SHA-256 是目前最常用的哈希算法。它输出 256 位,也就是 32 个字节。我当年做第一个安全启动项目时,用的就是它。
- 抗原像性:给定一个哈希值,你几乎不可能反推出原始数据。这叫「单向性」。
- 抗第二原像性:给定一个数据和它的哈希值,你找不到另一个数据产生同样的哈希值。
- 抗碰撞性:你找不到任意两个不同的数据,它们的哈希值相同。
嗯,这里要注意第三点。理论上,碰撞是存在的,因为输入空间无限,输出空间有限。但 SHA-256 的碰撞概率低到可以忽略不计。我见过有人担心这个,其实大可不必——除非你面对的是国家级攻击者。
来看一个简单的 Python 示例,计算字符串的 SHA-256 哈希值:
import hashlib
data = b"Hello, Secure Boot!"
hash_obj = hashlib.sha256(data)
digest = hash_obj.hexdigest()
print(f"原始数据: {data}")
print(f"SHA-256 哈希: {digest}")
print(f"哈希长度: {len(digest)} 个十六进制字符")
输出结果会是一个 64 个字符的十六进制串。你改一个字母试试?整个哈希值会变得面目全非。这就是所谓的「雪崩效应」。
2.2 数字签名:用私钥「盖章」
哈希函数只能保证数据没被篡改,但它不能证明这个数据是谁发的。你想想看,如果攻击者把固件和它的哈希值一起替换了,你怎么知道哪个是真的?
数字签名解决了这个问题。它用一对密钥:私钥签名,公钥验签。私钥只有你一个人有,公钥可以公开。
目前主流的有两种:RSA 和 ECDSA。
| 特性 | RSA | ECDSA |
|---|---|---|
| 安全性基础 | 大整数分解 | 椭圆曲线离散对数 |
| 密钥长度 | 2048/4096 位 | 256/384 位 |
| 签名速度 | 较慢 | 较快 |
| 验签速度 | 较快 | 较慢 |
| 典型应用 | 传统 PKI、代码签名 | 嵌入式、IoT、区块链 |
我个人更倾向于在嵌入式场景中使用 ECDSA。为什么?因为密钥短,计算快,省电。我做过一个项目,MCU 只有 64KB 的 Flash,跑 RSA-2048 签名验证要好几秒,换成 ECDSA-P256 后,几百毫秒就搞定了。
数字签名的流程是这样的:
- 对原始数据计算哈希值(比如 SHA-256)。
- 用私钥对这个哈希值进行加密,得到签名。
- 把原始数据和签名一起发送出去。
- 接收方用公钥解密签名,得到哈希值 A。
- 接收方自己对原始数据计算哈希值 B。
- 比较 A 和 B,一致则签名有效。
你看,这里哈希函数和数字签名是配合使用的。哈希函数负责压缩数据,数字签名负责保护哈希值。
2.3 公钥基础设施:信任的「身份证系统」
好,现在你有了一对密钥。你把公钥发给别人,别人用它来验证你的签名。但问题来了:你怎么证明这个公钥真的是你的?
这就是 PKI 要解决的问题。PKI 是一个完整的信任体系,核心是证书颁发机构(CA)。CA 就像公安局,它给你发一张「数字身份证」——也就是数字证书。
数字证书里包含什么?
- 持有者的公钥
- 持有者的身份信息(比如公司名、域名)
- 证书的有效期
- CA 的数字签名
- 证书序列号等元数据
CA 用自己的私钥给你的证书签名。别人拿到你的证书后,用 CA 的公钥验证签名,就知道这个证书是真的。这就形成了一个信任链:
根 CA → 中间 CA → 终端证书
在安全启动中,这个信任链被固化在硬件里。芯片出厂时,根 CA 的公钥被烧录在一次性可编程存储器(OTP)中,不可更改。然后,每一级固件都由上一级的私钥签名,芯片用上一级的公钥验证。
- 根信任:芯片 ROM 中的根公钥(硬件不可变)
- 一级 Bootloader:由根私钥签名,验证后加载
- 二级 Bootloader:由一级私钥签名,验证后加载
- 操作系统/应用:由二级私钥签名,验证后加载
每一级都验证下一级的签名,环环相扣。只要根信任不被攻破,整个链条就是安全的。
我参与过一个车规级项目,客户要求支持证书吊销。什么意思?如果某个私钥泄露了,CA 可以发布一个证书吊销列表(CRL),告诉所有设备「这个证书不再可信」。设备在验证签名时,需要先检查 CRL。嗯,这增加了复杂度,但安全性提升了一个档次。
2.4 三者如何协同工作?
咱们来捋一捋。在安全启动中,这三个东西是这样配合的:
- 哈希函数:对固件镜像计算摘要,确保完整性。
- 数字签名:用私钥对摘要签名,确保真实性和不可否认性。
- PKI:通过证书链分发公钥,确保公钥的可信性。
说白了,哈希函数是「锁」,数字签名是「钥匙」,PKI 是「钥匙的身份证」。三者缺一不可。
最后,留个思考题给你:如果攻击者物理接触了设备,能不能绕过这个信任链?比如,直接读取 OTP 中的根公钥,然后伪造一个签名?
答案是不能。因为私钥不在设备里,攻击者拿不到。但有一种攻击叫「回滚攻击」——攻击者把固件降级到有漏洞的旧版本。怎么防?嗯,这就要用到「抗回滚计数器」了,那是后面章节的内容。
好,今天就到这里。下一节我们讲对称加密和密钥协商,那是另一个有趣的话题。