2、PKI体系基础:公钥基础设施概念、数字证书X.509标准、证书链信任模型

聊SM2证书链之前,得先把地基打牢。PKI这套东西,说白了就是解决一个核心问题:你怎么相信网络上那个自称是“张三”的人,真的是张三?

我早年做电子政务项目时,客户上来就问:“你们怎么保证我的公文没被篡改?”当时我给他画了个PKI的草图,他看完就懂了。嗯,今天咱们就把这张图画清楚。

2.1 公钥基础设施(PKI)概念

PKI不是某个软件,也不是某条命令。它是一套完整的规则、流程、软硬件和人员的组合。目标就一个:在开放网络环境中,安全地分发和管理公钥。

你想想看,非对称加密里,公钥本来就应该公开。但问题来了——你怎么知道你拿到的公钥,确实是对方的?中间人完全可以给你一个假公钥。PKI就是来解决这个信任问题的。

PKI的核心组成:

  • CA(证书认证机构)——签发证书的权威机构,是整个信任体系的起点
  • RA(注册机构)——负责审核用户身份,把审核结果告诉CA
  • 证书库——存储和发布证书及CRL(证书吊销列表)的地方
  • 终端实体——持有证书的用户或设备
  • 管理协议——如CMP、SCEP,用于证书的申请、更新、吊销

我个人习惯把PKI比作“网络身份证系统”。CA就是公安局,RA就是派出所,证书就是身份证。你拿着身份证去办事,对方不用认识你本人,认身份证就行。

2.2 数字证书与X.509标准

数字证书就是PKI里的“身份证”。它把公钥和身份信息绑定在一起,再由CA盖上数字签名。这个签名一旦盖上,谁想篡改证书内容,签名验证就会失败。

目前最通用的证书格式是X.509 v3。我在项目中对接过不少国密设备,它们签发的SM2证书,本质上也是X.509 v3格式,只是签名算法换成了SM2withSM3。

2.2.1 X.509证书结构

一张标准的X.509 v3证书,包含以下字段:

字段 说明 我的备注
版本号 目前主流是v3(值为2) v3才支持扩展项
序列号 CA签发的唯一编号 吊销时靠它定位
签名算法 如SM2withSM3、SHA256withRSA 国密场景就是SM2withSM3
颁发者 签发该证书的CA名称 DN格式,如CN=SM2 Root CA
有效期 notBefore ~ notAfter 注意时区问题
主体 证书持有者的名称 可以是个人、服务器、设备
主体公钥信息 算法标识 + 公钥值 SM2公钥是65字节(未压缩)
扩展项 密钥用法、基本约束、SAN等 证书链验证的关键
CA签名 CA用私钥对上述内容的签名 防篡改的核心

避坑指南:我曾经遇到一个案例,服务器证书的SAN(Subject Alternative Name)字段没配域名,结果浏览器一直报“证书名称不匹配”。查了两小时才发现是扩展项漏了。记住:现代浏览器优先看SAN,不看CN字段。

2.2.2 X.509 v3扩展项

扩展项是v3版本的精髓。没有扩展项,证书链就没法验证。几个关键扩展:

  • 基本约束(BasicConstraints)——标记该证书是否为CA证书,以及路径长度限制
  • 密钥用法(KeyUsage)——规定公钥用途,如数字签名、密钥加密
  • 扩展密钥用法(ExtendedKeyUsage)——更细粒度,如服务器认证、客户端认证
  • 主体密钥标识符(SubjectKeyIdentifier)——快速定位下一级证书的颁发者
  • 颁发者密钥标识符(AuthorityKeyIdentifier)——指向上一级证书

为什么说这些重要?因为证书链验证时,每一步都要检查:上级CA证书是否允许签发下级证书?如果根CA证书的BasicConstraints没设CA标志,那它签发的所有子证书都是非法的。

2.3 证书链信任模型

单张证书好理解,但实际场景里,CA不会直接用根证书去签每个终端证书。为什么?安全考虑。根证书私钥一旦泄露,整个信任体系就崩了。所以通常采用多层证书链:

  • 根CA——自签名,离线存储,极少使用
  • 二级CA(中间CA)——由根CA签发,负责签发终端证书
  • 终端实体证书——最终用户或服务器持有的证书

验证过程是从终端证书开始,逐级向上,直到找到一个自签名且受信任的根证书。这个路径就叫证书链。

注意:证书链验证不是简单的“上级签名下级”。它还要检查:

  • 每张证书是否在有效期内
  • 每张证书是否被吊销(查CRL或OCSP)
  • 每张证书的密钥用法是否允许当前操作
  • 路径长度是否超过BasicConstraints限制

下面这张图,是我当年给团队培训时画的。它清晰地展示了SM2证书链的信任传递过程:

SM2证书链信任模型 SM2证书链信任模型 根CA (自签名) SM2withSM3 二级CA 由根CA签发 终端实体证书 由二级CA签发 验证流程 1. 获取终端证书 2. 找到颁发者(二级CA) 3. 验证二级CA签名 4. 找到根CA 5. 验证根CA签名 6. 根CA在信任库中 7. ✅ 信任建立 信任传递方向 自下而上验证

这张图里,信任是自上而下传递的:根CA信任二级CA,二级CA信任终端实体。但验证是自下而上的:从终端证书开始,逐级向上验证签名,直到信任的根证书。

2.3.1 信任锚

信任锚(Trust Anchor)就是验证的终点。通常是一个预置在系统中的根证书。操作系统、浏览器、Java信任库都内置了一批根证书。国密场景下,需要把SM2根证书导入到系统的信任存储中。

我遇到过最头疼的问题是什么?某次对接政务平台,对方给了个SM2根证书,但格式是PEM,而我们的Java应用只认JKS。折腾了半天才转好。所以建议你提前确认好信任库的格式要求。

实用建议:在Linux系统中,SM2根证书可以放在 /etc/ssl/certs/ 目录下,然后运行 update-ca-certificates 更新信任库。如果是Java应用,用 keytool -importcert 导入到cacerts。

2.3.2 路径构建与路径验证

证书链验证分两步:路径构建和路径验证。

  • 路径构建:从终端证书出发,根据颁发者信息,找到上一级证书,重复直到根证书。这一步可能有多条路径,需要选一条合法的。
  • 路径验证:对选出的路径,逐级检查签名、有效期、吊销状态、密钥用法、基本约束等。

RFC 5280里把验证规则写得清清楚楚。但实际实现时,不同平台的细节有差异。比如OpenSSL和Java的证书路径构建算法就不完全一样。我建议你在开发阶段,用同一个库做验证,避免跨平台时出现“这边验证通过,那边验证失败”的尴尬。

2.4 国密SM2证书的特殊性

SM2证书遵循X.509 v3标准,但有几个国密特有的点:

项目 国际算法(RSA/ECC) 国密SM2
签名算法OID sha256WithRSAEncryption (1.2.840.113549.1.1.11) sm2signWithSM3 (1.2.156.10197.1.501)
公钥算法OID rsaEncryption (1.2.840.113549.1.1.1) sm2 (1.2.156.10197.1.301)
椭圆曲线参数 secp256r1等 sm2p256v1 (固定曲线)
签名值格式 DER编码的SEQUENCE DER编码的SEQUENCE(r,s)

说白了,SM2证书就是把算法标识和曲线参数换成国密标准,其他结构完全兼容X.509。所以如果你已经熟悉国际证书,上手SM2证书很快。

重要提醒:SM2的椭圆曲线是固定的,参数由国家标准规定。不要试图用其他曲线生成SM2密钥对,否则证书解析时会报“无效曲线参数”。我见过有人用secp256r1冒充SM2,结果CA直接拒签。

2.5 小结

PKI体系的核心就三件事:谁签发(CA)、签给谁(证书)、怎么验证(证书链)。X.509 v3标准把证书结构定死了,扩展项给了灵活性。证书链信任模型通过分层CA,既保证了安全,又兼顾了效率。