3、密码学基础(二):公钥基础设施(PKI)与证书链,X.509证书结构解析
上一讲我们聊了对称与非对称加密、哈希和签名这些基础工具。但有个问题一直悬着:你拿到了 Bob 的公钥,你怎么确定这公钥真的是 Bob 的?
这就是 PKI 要解决的核心问题——信任的起点。说白了,PKI 就是一套让公钥变得可信的管理体系。我早年做物联网固件升级时,就踩过没有 PKI 的坑:设备直接硬编码了一个公钥,结果密钥泄露后,所有设备都得返厂升级。嗯,从那以后,我再也不敢轻视证书管理了。
3.1 什么是 PKI?
公钥基础设施(Public Key Infrastructure,PKI)不是某个单一技术,而是一整套策略、硬件、软件和流程的组合。它的目标就三个:
- 绑定身份与公钥:通过数字证书,把“张三”和“张三的公钥”锁在一起。
- 提供信任路径:从你信任的根,一路验证到目标证书。
- 支持生命周期管理:证书颁发、更新、吊销,全流程可控。
PKI 的核心角色有这几个:
| 角色 | 全称 | 职责 |
|---|---|---|
| CA | 证书颁发机构 | 签发和吊销证书,PKI 的信任核心 |
| RA | 注册机构 | 验证申请者身份,把审核结果交给 CA |
| VA | 验证机构 | 提供证书状态查询(如 OCSP 响应) |
| EE | 终端实体 | 持有证书和私钥的最终用户或设备 |
我个人习惯把 PKI 比作身份证系统:CA 就是公安局,RA 是派出所,VA 是联网查询系统,EE 就是你手里的身份证。你想想看,没有公安局,谁敢随便相信一张身份证?
3.2 X.509 证书结构
X.509 是 PKI 中最通用的证书格式标准。我见过的嵌入式设备,从车规级 MCU 到低功耗蓝牙芯片,几乎都在用 X.509 v3 版本。它的结构其实很清晰,咱们拆开来看。
3.2.1 证书的基本字段
一个标准的 X.509 v3 证书包含以下核心字段:
- 版本号(Version):目前主流是 v3(值为 2)。
- 序列号(Serial Number):CA 颁发的唯一整数,用于标识证书。
- 签名算法(Signature Algorithm):CA 签名时用的算法,比如 sha256WithRSAEncryption。
- 颁发者(Issuer):签发该证书的 CA 的 Distinguished Name(DN)。
- 有效期(Validity):notBefore 和 notAfter,定义了证书的生效和过期时间。
- 主体(Subject):证书持有者的 DN。
- 主体公钥信息(Subject Public Key Info):持有者的公钥算法和公钥值。
- 扩展(Extensions):v3 引入的灵活区域,用于附加约束和用途。
这里有个细节我提醒一下:序列号在 CA 内部必须唯一。我曾经遇到过一个项目,CA 的序列号生成器出了 bug,重复了,结果证书链验证时出现了歧义。排查了两天才找到根因。
3.2.2 关键扩展字段
v3 扩展是 X.509 的精华。没有扩展,证书就是个简单的公钥容器。有了扩展,我们才能做细粒度的访问控制。
| 扩展名称 | OID | 作用 |
|---|---|---|
| Basic Constraints | 2.5.29.19 | 标记是否为 CA 证书,以及路径长度限制 |
| Key Usage | 2.5.29.15 | 限制密钥用途(数字签名、密钥加密等) |
| Extended Key Usage | 2.5.29.37 | 更细粒度的用途(服务器认证、代码签名等) |
| Subject Alternative Name | 2.5.29.17 | 主体别名,常用于 HTTPS 的多域名支持 |
| CRL Distribution Points | 2.5.29.31 | 指定证书吊销列表的获取地址 |
| Authority Information Access | 1.3.6.1.5.5.7.1.1 | 提供 CA 证书和 OCSP 响应器的地址 |
做固件签名时,我最关注的是 Key Usage 和 Extended Key Usage。比如,代码签名证书必须包含 digitalSignature 用途,并且 EKU 里要有 codeSigning。如果这两个没设对,操作系统或 Bootloader 会直接拒绝加载固件。
3.3 证书链与信任模型
证书链(Certificate Chain)是 PKI 里最核心的概念之一。你想想看,如果每个设备都要内置所有 CA 的根证书,那维护成本就太高了。证书链的思路是:你只需要信任一个根,然后通过链式验证,信任所有由该根签发的证书。
3.3.1 证书链的结构
一个典型的证书链有三层:
- 根 CA 证书(Root CA):自签名,信任锚点。通常离线存储,极其安全。
- 中间 CA 证书(Intermediate CA):由根 CA 签发,用于签发终端证书。可以有多级。
- 终端实体证书(Leaf/EE):由中间 CA 签发,用于实际通信或签名。
验证过程是从叶子往根走:
- 用中间 CA 的公钥验证叶子证书的签名。
- 用根 CA 的公钥验证中间 CA 证书的签名。
- 根 CA 是自签名的,你必须在本地信任它。
这里有个常见的误解:验证证书链时,不需要验证根证书的签名。因为根证书是信任锚点,你信任它,不是因为它签名了自己,而是因为你把它放进了信任存储区。
3.3.2 证书链验证的完整流程
我习惯把验证流程拆成四步:
- 有效期检查:每个证书的当前时间必须在 notBefore 和 notAfter 之间。
- 签名验证:从叶子开始,用上一级证书的公钥验证当前证书的签名。
- 名称链检查:当前证书的 Issuer 必须与上一级证书的 Subject 一致。
- 扩展约束检查:Basic Constraints、Key Usage、Path Length 等必须合规。
3.4 证书生命周期管理
证书不是永久的。从颁发到销毁,每个阶段都有对应的管理动作。
| 阶段 | 动作 | 说明 |
|---|---|---|
| 初始化 | 密钥生成、CSR 提交 | 私钥必须在安全环境中生成,CSR 包含公钥和身份信息 |
| 颁发 | CA 签发证书 | CA 验证 CSR 后,签发 X.509 证书并返回 |
| 使用 | 身份认证、签名、加密 | 证书在有效期内正常使用 |
| 更新 | 证书续期 | 在过期前重新签发,密钥可以不变或轮换 |
| 吊销 | CRL / OCSP | 私钥泄露或人员离职时,立即吊销证书 |
| 销毁 | 私钥安全删除 | 证书过期或吊销后,私钥必须彻底清除 |
吊销这块我多说两句。在嵌入式场景里,设备可能常年离线,没法实时查询 CRL 或 OCSP。怎么办?我常用的方案是短有效期证书:把证书有效期设为几天甚至几小时,过期自动失效,不需要吊销。这在物联网固件签名中特别实用。
3.5 证书链的视觉化
下面这张图展示了从根 CA 到终端设备的完整证书链结构,以及验证时的数据流向。
3.6 嵌入式 PKI 的常见坑
做嵌入式 PKI 和做 Web PKI 差别很大。我总结几个实际项目中踩过的坑:
- 证书太大:X.509 证书动辄 1-2KB,对于只有几十 KB Flash 的 MCU 来说,存几个证书就满了。我建议用证书压缩或只存指纹,验证时再获取完整证书。
- 时间同步难:很多设备没有 RTC 或无法联网校时,有效期检查就成了摆设。我的做法是用固件版本号代替时间戳,或者用单调计数器做相对时间验证。
- 私钥存储:私钥必须放在安全元件(SE)或 TEE 里。如果放在普通 Flash 里,攻击者用 JTAG 就能读出来。嗯,这个坑我早年也踩过。
- 证书链深度:链太长会导致验证时间变长,而且占用更多 RAM。我一般控制在 3 层以内(根 + 中间 + 叶子)。