上一篇已经把数字证书从 ASN.1 结构一路还原成 DER 字节。但字节只是容器,真正决定一张证书“声明了什么、允许做什么”的,是它里面的字段和扩展。
打开一张证书,我们往往会看到版本号、序列号、签发者、主体、有效期、公钥,以及 SAN、Key Usage、Basic Constraints 等一长串扩展。这些信息不是平铺的属性列表,而是一套有层次的声明:
这篇文章就沿着这三层结构,拆开一张 X.509 v3 证书。
一、外层 Certificate:声明与签名如何组合
X.509 证书最外层的 ASN.1 结构只有三部分:
tbsCertificate:被签名的证书正文
TBS 是 To Be Signed 的缩写。版本、序列号、签发者、主体、公钥和所有扩展都放在这里。CA 对 tbsCertificate 的 DER 字节计算签名,因此其中任何一个字节被改动,签名都会失效。
signatureAlgorithm:CA 用了什么签名方案
这里保存签名算法的 OID 和必要参数,例如 RSA-PSS 或 ECDSA with SHA-256。TBSCertificate 内部也有一个 signature 字段,它表示 CA 计划用来签署证书的算法;外层 signatureAlgorithm 则伴随实际签名值。两者应保持一致,当前公开信任的 TLS 证书规则进一步要求两处编码值逐字节相同。
signatureValue:CA 生成的签名值
验证方使用签发者的公钥验证这个值。验签成功只能说明 tbsCertificate 在签发后没有被篡改,并且签名者控制对应私钥。至于这个签发者是否受信、证书是否被吊销、是否允许当前用途,还要由后续验证完成。
证书签名正确 ≠ 证书可信。 前者是密码学判断,后者还需要信任锚、路径、时间、状态和用途策略。
二、先看一张证书的整体样子
下面是一份经过简化的教学证书输出。example.test 用于示例,不代表真实站点或公开受信证书。
这份输出正好对应前面的三层结构:Data 展开被签名的证书正文,X509v3 extensions 补充身份与用途约束,末尾的 Signature Algorithm 和 Signature Value 则属于外层签名。这里先认识各部分的位置,文章最后再给出一套完整的阅读顺序。
三、TBSCertificate:证书的主干字段
1. Version:为什么 v3 显示成 0x2
X.509 定义了 v1、v2 和 v3 三个版本,但 ASN.1 枚举从 0 开始:
| 人类名称 | ASN.1 枚举值 | OpenSSL 常见显示 |
|---|---|---|
| v1 | 0 | 1 (0x0) |
| v2 | 1 | 2 (0x1) |
| v3 | 2 | 3 (0x2) |
因此 Version: 3 (0x2) 不是版本号冲突,而是“第三版、内部枚举值为 2”。只有 v3 证书才能携带 extensions,这也是现代 PKI 基本上都使用 v3 的原因。
2. Serial Number:与签发者一起唯一定位证书
序列号由 CA 分配。RFC 5280 要求它是正整数,同一签发者不得为两张证书分配相同序列号,且符合实现必须能处理最多 20 个八位组的序列号。
序列号并不需要在全世界唯一,真正的定位组合是:
对公开信任的 TLS 证书,当前 CA/B Forum Baseline Requirements 还要求序列号大于 0、小于 2¹⁵⁹,并至少包含来自密码学安全伪随机数生成器的 64 位输出。这是 Web PKI 的更严格规则,不是所有私有 PKI 都会自动遵循。
3. Signature:正文内部的签名算法声明
这是 TBSCertificate 内部的算法标识,不是签名值本身。它要与证书外层的 signatureAlgorithm 一致。阅读工具常常会把两处都打印为 Signature Algorithm,所以会在输出中看到两次。
4. Issuer:谁对这张证书负责
issuer 是签发者的 X.500 Distinguished Name(DN)。它可以包含 C、O、OU、CN 等多个属性,并不是一段普通的逗号分隔字符串。
issuer 会参与证书链上的签发者匹配,但它只是名称线索。名称相同不代表公钥相同,更不代表已经建立信任。
5. Validity:声明可接受的时间区间
validity 包含 notBefore 和 notAfter。按 RFC 5280 的 Internet PKI profile,2050 年以前的时间使用 UTCTime,2050 年及以后使用 GeneralizedTime,两者都以 Zulu/GMT 形式编码到秒。
应用会判断当前验证时间是否落在该区间内。但实际系统还需要考虑可信时钟、允许的误差和业务验证时点。“尚未过期”也不等于“尚未吊销”。
6. Subject:证书正文中的主体名称
subject 同样是 X.500 DN。它可以表示一个人、组织、设备或服务,但不同证书 profile 允许的属性并不相同。
当主体身份只写在 subjectAltName 中时,subject 可以是空 SEQUENCE,此时 SAN 必须标记为关键扩展。对当前公开信任的 TLS 服务器证书,域名或 IP 身份必须出现在 SAN;commonName 已不是推荐的主身份位置。
7. Subject Public Key Info:算法和公钥必须一起读
subjectPublicKeyInfo(SPKI)由两部分组成:
algorithm 说明如何解释后面的公钥字节。例如 RSA 公钥需要读取模数和指数,椭圆曲线公钥则还要确认曲线参数。不能只抽出 BIT STRING 就猜测公钥类型。
8. Unique ID 与 Extensions
issuerUniqueID 和 subjectUniqueID 是为 v2 引入的历史字段,v3 仍可编码,但 RFC 5280 要求符合的 CA 不生成它们,符合的应用即使收到也应能处理。
extensions 则是 v3 证书的核心。每个扩展都包含:
extnValue 内部通常还包着该扩展自己的 DER 结构,所以它是“DER 里再包一层 DER”,不是一段可直接阅读的文本。
四、Critical:它表示“不理解就不能用”
critical 最容易被误解为“这个扩展特别重要”。它实际上定义的是验证器无法理解或处理扩展时的处置方式:
- 未识别,或者虽已识别但无法处理的关键扩展:必须拒绝该证书;
- 未识别的非关键扩展:可以忽略,继续处理其他内容。
这并不意味着非关键扩展没有安全意义。SAN、EKU、AIA 和证书策略通常都可能是非关键的,但应用一旦识别它们,就必须按对应语义处理,不能因为 critical 为 FALSE 就随意忽略。
critical是“不理解时怎么办”的协议开关,不是安全等级标签。
五、七组常用扩展,分别回答不同问题
1. Basic Constraints:这张证书能不能当 CA
basicConstraints 主要包含:
cA:主体是否可以被当作 CA;pathLenConstraint:在一条有效路径中,该 CA 之后最多还允许出现多少张非自颁发(non-self-issued)的中间 CA 证书。
“自颁发”是指证书的 subject 与 issuer 相同,不等同于“自签名”。例如 CA 换钥时,新旧密钥之间可能签发自颁发但并非自签名的证书;RFC 5280 在计算 pathLenConstraint 时不把这类证书计入层数。
一张终端证书通常显示 CA:FALSE。CA 证书要用于验证下级证书签名时,除了 cA=TRUE,还要看 Key Usage 是否包含 keyCertSign。两者是配合关系,不能只看其中一个。
2. Subject Alternative Name:这张证书代表哪些身份
SAN 可以包含多种 GeneralName:
| 形式 | 常见用途 |
|---|---|
dNSName | 域名 |
iPAddress | IPv4 或 IPv6 地址 |
rfc822Name | 电子邮箱 |
uniformResourceIdentifier | URI 身份 |
directoryName | X.500 DN |
otherName | 由其他 OID 定义的身份 |
对 Web 服务器证书,域名和 IP 匹配要看 SAN,不应只看 subject 里的 CN。而在邮件、设备、企业内网等 profile 中,允许的 SAN 形式和验证方法可能不同。
3. Key Usage:公钥可以参与哪类密码操作
Key Usage 是一组比特位,常见值包括:
| 值 | 含义 |
|---|---|
digitalSignature | 验证普通数据签名,不包括证书和 CRL 签名 |
contentCommitment | 历史名称为 nonRepudiation,表示承诺型内容签名用途 |
keyEncipherment | 加密或传递其他密钥,常见于 RSA 密钥封装 |
dataEncipherment | 直接加密用户数据,不是密钥 |
keyAgreement | 密钥协商 |
keyCertSign | 验证证书签名,只应用于 CA 证书 |
cRLSign | 验证 CRL 签名 |
Key Usage 表达的是底层密码能力,不直接等于“服务器证书”或“代码签名证书”这种应用角色。
4. Extended Key Usage:证书允许进入哪类应用
EKU 使用 OID 表示更具体的应用目的:
| EKU | OID | 用途 |
|---|---|---|
serverAuth | 1.3.6.1.5.5.7.3.1 | TLS 服务器认证 |
clientAuth | 1.3.6.1.5.5.7.3.2 | TLS 客户端认证 |
codeSigning | 1.3.6.1.5.5.7.3.3 | 代码签名 |
emailProtection | 1.3.6.1.5.5.7.3.4 | 邮件保护 |
timeStamping | 1.3.6.1.5.5.7.3.8 | 时间戳签名 |
OCSPSigning | 1.3.6.1.5.5.7.3.9 | OCSP 响应签名 |
如果 Key Usage 和 EKU 同时存在,验证器要同时处理两者;只有它们共同允许的用途才能继续。例如,一张证书的 EKU 只有 serverAuth,就不应因为 Key Usage 包含 digitalSignature 而被当成代码签名证书。
5. AKI 与 SKI:为证书链提供密钥线索
- Subject Key Identifier(SKI):标识当前证书中的主体公钥;
- Authority Key Identifier(AKI):帮助定位签发这张证书的 CA 密钥。
一个 CA 名称可能在密钥轮换后保持不变,AKI/SKI 可以帮助路径构建器在多张同名 CA 证书中选择候选者。但它们只是定位线索,不能代替签名验证和信任锚判断。
原书基于早期 RFC 3280 材料,将 SKI 写成必须标记为关键扩展。现行 RFC 5280 的 Internet PKI profile 要求 SKI 保持非关键,续写时不应照搬旧表。
6. Certificate Policies 与 Name Constraints:这条路径受什么政策限制
certificatePolicies 通过 OID 声明证书按哪套策略签发,还可以指向 CPS。一个策略 OID 本身只是索引,它的保证水平取决于策略文档、审核要求和信任方的处理规则。
nameConstraints 通常用在 CA 证书上,限制后续路径中允许或禁止的 DNS、IP、邮箱或 DN 命名空间。它不是终端证书上的普通备注,而是会改变路径验证结果的约束。
7. AIA 与 CRL Distribution Points:去哪里找签发者和状态信息
- Authority Information Access(AIA) 常见地提供 OCSP 服务地址或 CA 证书下载地址;
- CRL Distribution Points(CRLDP) 提供 CRL 发布位置。
它们保存的是“到哪里获取信息”,不是“当前证书一定有效”。查到地址后,验证方还需要获取数据、验证响应或 CRL 的签名与新鲜度,再按本地策略决定如何处理网络失败。
六、一张 Web 服务器证书,字段应该如何配合
把前面的字段放进一个具体场景,会更容易看懂它们各自的职责。对一张当前公开信任的 TLS 服务器证书:
| 问题 | 主要字段 | 典型判断 |
|---|---|---|
| 它代表哪个站点? | SAN | 至少包含一个经验证的 dNSName 或 iPAddress |
| 它是不是 CA? | Basic Constraints | 扩展可以省略;如果存在,cA 必须为 FALSE,且不得包含 pathLenConstraint |
| 公钥可以做什么? | Key Usage | 按 RSA 或 ECC 公钥类型限定签名、密钥封装等操作 |
| 它可以进入什么应用? | EKU | 包含 serverAuth,不因为能签名就顺便用于代码签名 |
| 如何找上级 CA 和状态服务? | AKI、AIA、CRLDP | 只提供路径和状态数据的候选线索 |
| 哪套签发规则适用? | Certificate Policies | 读取策略 OID,必要时回到 CP/CPS |
当前 CA/B Forum Baseline Requirements 对公开信任 TLS 证书的要求比通用 RFC 5280 profile 更具体:SAN 必须存在,serverAuth EKU 必须存在,commonName 不推荐使用,如果存在还必须来自 SAN 中的值。
这个例子也说明,X.509 只提供可表达的字段,具体 profile 才决定字段必须怎么组合。把 Web PKI 的规则原样套到企业内部 CA、邮件证书或国密双证书体系,并不一定正确。
七、用 OpenSSL 按层检查证书
首先打印整体内容:
如果只想核对主干字段:
单独查看关键扩展:
检查证书是否匹配特定主机名:
这些命令能回答“证书里写了什么”,但不能单独完成整个信任判断。完整验证还需要明确信任锚、中间证书、验证用途、时间和吊销策略。
八、一张证书的正确阅读顺序
面对一张陌生证书,可以按以下顺序检查:
- 外层结构:证书是否能正确解析,内外签名算法是否一致;
- 基本声明:签发者、主体、序列号、有效期和 SPKI 是什么;
- 身份声明:当前场景应当匹配 subject 还是 SAN;
- 能力限制:Basic Constraints、Key Usage 和 EKU 是否同时允许当前用途;
- 路径线索:AKI、AIA、CRLDP 和证书策略提供了哪些候选信息;
- 信任验证:再去构建路径、验证签名、时间、吊销状态与业务授权。
前五步在阅读证书的“声明”,第六步才是判断这些声明在当前环境中能否被接受。
字段告诉你证书声称什么,扩展告诉验证器应当如何限制它;信任链和本地策略才决定应用是否接受它。
下一篇将先暂停在信任判断之前,处理一个更实际的问题:证书、私钥和证书链分别装在 PKCS#7、PKCS#8 和 PKCS#12 的什么位置,以及为什么扩展名不能代表真实格式。
参考资料
- RFC 5280:Internet X.509 公钥基础设施证书与 CRL Profile
- RFC 6818:RFC 5280 的规范更新
- CA/Browser Forum:Server Certificate Baseline Requirements v2.2.8(2026-06-16;本文核验于 2026-08-04)
- OpenSSL x509 官方文档
系列文章
- 理解PKI(一):从密码学历史到公钥基础设施
- 理解PKI(二):从 ASN.1 到 DER,数字证书为什么是一串字节
- 本篇:拆开 X.509 v3,读懂证书的核心字段与扩展
- 下一篇:证书、私钥与容器——PKCS#7、PKCS#8、PKCS#12 有什么区别
笔记整理自《PKI_CA与数字证书技术大全》第三部分第 9 章,并按 RFC 5280 及当前公开信任 TLS 证书 profile 校正和补充。
