3、密码学基础:公钥基础设施(PKI)、数字签名、哈希算法、证书链的概念,以及它们在Secure Boot中的应用
Secure Boot 的信任根建立在密码学原语之上。要理解固件如何被验证、签名如何被校验、以及平台如何信任一个未知的公钥,必须掌握四个核心概念:哈希算法、数字签名、公钥基础设施(PKI)和证书链。本章将从数学原理出发,逐步拆解这些概念在 UEFI Secure Boot 启动流程中的具体落点,并给出可操作的验证方法和常见误区。
3.1 哈希算法:数据指纹与完整性保证
核心原理
哈希算法(Hash Algorithm)将任意长度的二进制数据映射为固定长度的输出值,称为摘要(Digest)或指纹。SHA-256 是 Secure Boot 中最常用的算法,输出 256 位(32 字节)的摘要。其数学特性包括:单向性(无法从摘要反推原文)、抗碰撞性(难以找到两个不同输入产生相同输出)、雪崩效应(输入微变,输出剧变)。在 Secure Boot 中,哈希用于两个关键场景:一是对固件镜像计算摘要,作为签名的对象;二是对证书或公钥本身计算哈希,用于在白名单中快速匹配。
判断方法与操作流程
在 Linux 环境下,可以使用以下命令验证固件镜像的哈希值:
# 计算固件文件的 SHA-256 哈希
sha256sum firmware.bin
# 使用 OpenSSL 计算并输出十六进制摘要
openssl dgst -sha256 -hex firmware.bin
# 对比两个文件的哈希是否一致
echo "预期哈希值 firmware.bin" | sha256sum -c -
在实际 Secure Boot 验证流程中,UEFI 固件会先读取镜像文件,计算其 SHA-256 摘要,然后使用平台公钥解密签名值,得到厂商在签名时计算的原始摘要。两者比对一致,则完整性验证通过。
案例拆解:固件被篡改后的哈希变化
假设某设备厂商发布 BIOS 更新包 BIOS_2024.bin,原始 SHA-256 为 3a7b...f9e2。攻击者在传输过程中修改了 1 个字节(例如将版本号从 1.2 改为 1.3),重新计算哈希得到 8c1d...a4b7。由于雪崩效应,两个摘要完全不同。UEFI 固件在验证时发现签名解密后的摘要与重新计算的摘要不一致,立即拒绝加载该镜像。这个案例说明哈希算法是检测篡改的第一道防线,但哈希本身不提供身份认证——攻击者可以同时替换镜像和哈希值,因此必须依赖数字签名。
常见误区与总结
总结:哈希是 Secure Boot 的“体检工具”,它快速检查镜像是否被改动,但无法回答“这个镜像来自谁”的问题。该问题由数字签名解决。
3.2 数字签名:身份认证与防抵赖机制
核心原理
数字签名基于非对称加密算法(如 RSA、ECC)。签名者使用私钥对数据的哈希值进行加密运算,生成签名;验证者使用公钥进行解密运算,还原出哈希值并与实际计算的哈希比对。如果一致,则证明:①数据确实来自持有私钥的一方;②数据在签名后未被修改。RSA-2048 是当前 Secure Boot 的主流选择,部分新平台开始支持 ECDSA-256 以降低计算开销。
操作流程:签名生成与验证
以下命令演示了使用 OpenSSL 对固件镜像进行签名和验证的完整流程:
# 生成 RSA 密钥对(私钥 + 公钥)
openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -in private.pem -pubout -out public.pem
# 对固件镜像进行签名(先哈希,再用私钥加密)
openssl dgst -sha256 -sign private.pem -out firmware.sig firmware.bin
# 验证签名(用公钥解密签名,与本地计算的哈希比对)
openssl dgst -sha256 -verify public.pem -signature firmware.sig firmware.bin
在 UEFI 环境中,验证过程由固件内部的密码学模块完成,不依赖操作系统。平台固件从签名数据库中加载公钥,对加载的驱动或应用执行上述验证逻辑。
案例拆解:签名密钥泄露的后果
2016 年,某知名主板厂商的 Secure Boot 签名私钥意外泄露。攻击者使用该私钥对恶意 bootkit 进行签名,使其通过所有 UEFI 安全验证。该事件导致大量设备面临启动级恶意软件风险。复盘发现:厂商将私钥存储在联网的构建服务器上,且未实施硬件安全模块(HSM)保护。修复措施包括:吊销所有旧证书、发布新密钥对、强制用户更新固件以替换内嵌公钥。这个案例说明,数字签名的安全性完全依赖于私钥的保密性,密钥管理是 PKI 的核心挑战。
常见误区与总结
总结:数字签名将“数据完整性”与“身份真实性”绑定在一起。没有签名,攻击者可以同时替换镜像和哈希值;有了签名,攻击者必须获得私钥才能伪造合法签名。
3.3 公钥基础设施(PKI)与证书链
核心原理
PKI 是一套管理密钥和证书的完整体系,包括证书颁发机构(CA)、注册机构(RA)、证书吊销列表(CRL)和证书存储库。在 Secure Boot 中,PKI 定义了信任的层级关系:平台密钥(PK)是信任根,由平台所有者(通常是用户或企业 IT)控制;密钥交换密钥(KEK)用于管理签名数据库(db)和禁止签名数据库(dbx)的更新;db 包含受信任的签名公钥或镜像哈希;dbx 包含被吊销的签名或哈希。证书链的验证方向是从叶子证书(如驱动签名证书)逐级向上,直到信任锚(PK)。
| PKI 组件 | Secure Boot 对应角色 | 功能说明 | 存储位置 |
|---|---|---|---|
| 根 CA 证书 | 平台密钥(PK) | 信任根,控制 KEK 的更新 | UEFI NVRAM |
| 中间 CA 证书 | KEK | 管理 db/dbx 的签名更新 | UEFI NVRAM |
| 叶子证书 | db 中的签名证书 | 授权具体固件/驱动的加载 | UEFI NVRAM |
| 吊销列表 | dbx | 阻止已知恶意或过期签名 | UEFI NVRAM |
判断方法与验证流程
证书链验证遵循“自下而上”的路径:
- UEFI 固件加载一个驱动,其签名附带证书链(驱动证书 → 中间 CA → 根 CA)。
- 固件首先检查驱动证书是否在 db 列表中(直接匹配或通过哈希匹配)。
- 若不在 db 中,则尝试构建证书链:使用中间 CA 的公钥验证驱动证书的签名,再使用 PK 的公钥验证中间 CA 的签名。
- 如果链上所有签名都有效,且根证书与 PK 匹配,则验证通过。
- 同时检查 dbx 列表,确认链上任何证书未被吊销。
在 Linux 系统中,可以使用 sbverify 工具检查一个 EFI 二进制文件的签名信息:
# 查看签名证书的详细信息
sbverify --list /boot/efi/EFI/ubuntu/shimx64.efi
# 使用平台证书验证签名
sbverify --cert db_cert.pem /boot/efi/EFI/ubuntu/shimx64.efi
案例拆解:企业批量部署中的 PKI 设计
某大型企业有 5000 台工作站,需要统一管理 Secure Boot。初始状态是每台设备使用厂商默认的 Microsoft 证书。IT 部门决定建立企业自己的 PKI:
- 约束:不能中断现有系统启动,需要平滑过渡;必须支持远程管理。
- 方案:创建企业根 CA,签发新的 PK 和 KEK。先通过 BIOS 配置工具将企业 PK 添加到设备的“平台密钥”槽位,同时保留 Microsoft 的 KEK 和 db 条目,确保现有系统仍可启动。
- 操作:使用
KeyTool.efi在 UEFI Shell 中更新 NVRAM 变量;通过 SCCM 远程推送固件更新脚本。 - 结果:两周内完成 5000 台设备的 PK 替换,所有设备成功启动。后续发布内部开发的诊断工具时,使用企业 CA 签名的证书加入 db,即可在所有设备上运行。
- 风险与代价:如果企业根 CA 私钥泄露,攻击者可以签发任意受信任的固件。因此私钥存储在离线 HSM 中,只有两名管理员持有访问卡。
复盘经验:PKI 设计的关键是“信任根的安全”和“吊销路径的可用性”。企业应定期轮换 KEK,并建立 dbx 更新机制以应对证书泄露事件。
常见误区与总结
总结:PKI 提供了可扩展的信任管理框架。在 Secure Boot 中,PK 是“你信任谁”的最终答案,KEK 是“谁可以修改信任列表”的授权书,db/dbx 是具体的黑白名单。理解这个层级关系,是配置和管理 Secure Boot 的基础。
3.4 四者协同:Secure Boot 的完整验证链路
核心原理
哈希、签名、PKI 和证书链并非孤立工作,而是构成一条完整的验证流水线。以启动一个 UEFI 驱动为例:固件首先从 db 中查找匹配的签名证书;找到后,使用该证书的公钥验证驱动镜像的数字签名;验证过程中,先对镜像计算 SHA-256 哈希,再用公钥解密签名值,比对两者;最后,固件回溯证书链,确认该证书确实由 KEK 或 PK 签发。只有全部通过,驱动才会被加载。
操作流程:手动模拟验证链路
以下命令模拟了从镜像到证书链的完整验证过程:
# 1. 计算镜像哈希
sha256sum driver.efi
# 2. 提取签名值(假设为 PKCS#7 格式)
openssl pkcs7 -inform DER -in driver.p7b -print_certs -noout
# 3. 使用 db 中的公钥验证签名
openssl smime -verify -inform DER -in driver.p7b -content driver.efi -CAfile db_certs.pem
# 4. 检查证书链是否有效
openssl verify -CAfile pk_cert.pem -untrusted keks.pem driver_cert.pem
在实际 UEFI 环境中,这些步骤由固件中的 VerifyImageInMemory 函数自动完成,开发者可以通过 EDK2 的 SecurityPkg 源码了解实现细节。
案例拆解:一次完整的启动验证过程
一台联想 ThinkPad 笔记本启动时,UEFI 固件按以下顺序验证:
- 加载
shim.efi(第一阶段引导加载程序),其签名证书是 Microsoft 的,位于 db 中。 - 固件计算 shim 的 SHA-256,使用 Microsoft 公钥解密签名,比对成功。
- 固件检查 Microsoft 证书是否在 dbx 中(未被吊销),确认后加载 shim。
- shim 自身包含一个内嵌证书(MokList),用于验证下一阶段的 GRUB2 引导加载程序。
- GRUB2 验证 Linux 内核的签名,内核验证模块签名。每一级都重复哈希+签名+证书链的流程。
整个链路耗时约 200ms,其中大部分时间用于 RSA-2048 解密运算。如果使用 ECDSA-256,可缩短至 50ms 以内。这个案例展示了 Secure Boot 如何通过分层验证实现“从电源键到内核”的完整信任链。
常见误区与总结
总结:哈希提供完整性检查,签名提供身份认证,PKI 提供信任管理,证书链提供层级验证。四者协同,构成了 Secure Boot 的完整安全模型。在实际部署中,需要同时关注算法强度、密钥保护和证书生命周期管理,才能构建真正可信的启动环境。