2. X.509标准:证书版本、序列号、签名算法、颁发者、有效期、主体、公钥信息、扩展项

X.509 是什么?说白了,它就是数字证书的“通用语言”。

我刚开始接触 PKI 的时候,觉得证书就是一串乱码。后来被坑了几次才明白——证书里的每个字段都有它的脾气。你如果不了解这些字段,后面做证书链验证的时候,连报错都看不懂。

这一章,咱们就把 X.509 证书的骨架拆开来看。一共八个核心字段,我一个一个讲。

一句话总结:X.509 定义了证书长什么样,每个字段干什么用。你只要记住这八个字段,就能看懂任何一张证书。

2.1 证书版本(Version)

版本号就三个值:v1、v2、v3。现在几乎全是 v3。

为什么?因为 v1 和 v2 不支持扩展项。没有扩展项,你就没法做证书链约束、没法做密钥用法限制。我在项目中见过有人拿 v1 证书做双向认证,结果死活配不通——嗯,就是因为扩展项缺失,客户端不认。

版本 特点 现状
v1 最基础,无扩展项 基本淘汰
v2 增加了颁发者和主体唯一标识 极少使用
v3 支持扩展项,功能完整 当前标准

我的习惯:不管什么场景,一律用 v3。省得后面扩展项不够用,还得重新签发。

2.2 序列号(Serial Number)

序列号就是证书的“身份证号”。同一个 CA 签发的证书,序列号必须唯一。

我记得有一次排查证书吊销问题,发现两张证书的序列号竟然一样。查了半天,原来是 CA 的序列号计数器重置了。你想想看,序列号重复意味着什么?吊销列表(CRL)里根本分不清吊销的是哪一张。

避坑指南:我曾经遇到过某厂商的 CA 产品,序列号只用了 4 个字节。结果证书量一大,就撞上了。现在标准要求至少 8 字节,我建议直接用 20 字节,跟 SHA-1 哈希一样长,基本不会重复。

2.3 签名算法(Signature Algorithm)

这个字段告诉你怎么验证这张证书的签名。它通常和证书末尾的签名值配套出现。

常见的组合:

  • SHA256withRSA:最主流,兼容性好
  • SHA384withECDSA:性能更好,密钥更短
  • SHA1withRSA:已经过时,别再用了

我个人的建议是:新系统一律用 ECDSA。RSA 虽然稳,但密钥太长,握手时慢。ECDSA 用 P-256 曲线,又快又安全。

2.4 颁发者(Issuer)

颁发者就是签发这张证书的 CA 的名字。它用 DN(Distinguished Name)来表示。

一个典型的 DN 长这样:

CN=MyRootCA, O=MyCompany, C=CN

这里 CN 是通用名称,O 是组织,C 是国家。你可能会问:为什么要有这么复杂的命名规则?

因为证书链验证的时候,子证书的颁发者 DN 必须和父证书的主体 DN 完全一致。我在项目中遇到过因为多了一个空格,导致证书链验证失败的情况。嗯,字符串比对就是这么严格。

2.5 有效期(Validity)

有效期包含两个时间点:生效时间(notBefore)和失效时间(notAfter)。

这里有个坑:很多人在代码里直接拿系统时间跟有效期比对。但如果系统时间不准,证书可能提前过期或者还没生效就被判定无效。

我的做法:校验有效期时,留一个 5 分钟的“宽容窗口”。也就是 notBefore 前 5 分钟就算生效,notAfter 后 5 分钟才算过期。这样能避免时钟偏差导致的误判。

另外,有效期越长越不安全。根证书我建议 10-20 年,中间 CA 5 年,终端证书 1-2 年。别图省事签个 10 年的终端证书——密钥泄露了你就哭吧。

2.6 主体(Subject)

主体就是证书持有者的身份。如果是服务器证书,主体通常是域名;如果是个人证书,主体就是姓名和邮箱。

举个例子:

CN=www.example.com, O=Example Inc., L=Beijing, C=CN

这里 CN 是域名。浏览器在验证 HTTPS 时,会拿这个 CN 跟你访问的域名比对。如果不匹配,浏览器就会弹出安全警告。

注意:现在更推荐用 subjectAltName 扩展来放域名,而不是 CN。因为 CN 只能放一个域名,而 subjectAltName 可以放多个。我曾经见过一张证书 CN 写的是 IP 地址,结果 Chrome 直接报错——因为 Chrome 早就不认 CN 里的 IP 了。

2.7 公钥信息(Subject Public Key Info)

这个字段包含两部分:公钥算法和公钥值。

公钥算法告诉你这是 RSA 还是 ECDSA。公钥值就是那个长长的二进制串。

你可能会想:公钥放在证书里,那私钥呢?私钥当然是自己保管好。证书只负责把公钥和身份绑定在一起。

算法 密钥长度 安全强度
RSA 2048 位 中等
RSA 4096 位 高
ECDSA P-256(256 位) 高
ECDSA P-384(384 位) 极高

我个人习惯:服务器证书用 ECDSA P-256,性能好,安全性也够。根证书用 RSA 4096,兼容性最广。

2.8 扩展项(Extensions)

扩展项是 v3 证书的灵魂。没有扩展项,证书就是个“裸身份”,啥约束都没有。

常见的扩展项有:

  • Basic Constraints:标记这是 CA 证书还是终端证书。CA 证书才能签发子证书。
  • Key Usage:限制密钥用途。比如 digitalSignature 只能用于签名,keyEncipherment 只能用于加密。
  • Extended Key Usage:更细的用途限制。比如 serverAuth 只能用于服务器认证,clientAuth 只能用于客户端认证。
  • Subject Alternative Name:放域名、IP、邮箱等。
  • CRL Distribution Points:告诉你去哪里下载证书吊销列表。

核心原则:扩展项是用来“收窄”证书权限的。不要给终端证书加 CA 标志,不要给服务器证书加代码签名用途。权限越小,出事后的损失越小。

我曾经接手过一个项目,所有证书都是用同一个 CA 模板签发的。结果终端证书居然带了 CA:TRUE 的扩展项。这意味着任何一张终端证书都能签发新的证书——整个信任体系瞬间崩塌。

2.9 知识结构图

下面这张图把 X.509 证书的八个核心字段串起来了。你可以看到它们之间的层级关系:

X.509 证书核心字段结构图 X.509 证书核心字段结构 X.509 v3 证书 版本 (Version) v1 / v2 / v3 序列号 (Serial) 唯一标识 签名算法 SHA256withRSA 有效期 notBefore/notAfter 颁发者 (Issuer) CN=MyCA, O=MyOrg 主体 (Subject) CN=www.example.com 公钥信息 RSA 2048 / ECDSA P-256 扩展项 (Extensions) Basic Constraints | Key Usage | Extended Key Usage | Subject Alternative Name | CRL Distribution Points 签名值 (Signature Value) 由颁发者私钥签名 扩展项是 v3 证书的核心能力,证书链验证的约束条件全靠它

2.10 小结

X.509 证书的八个字段,每个都有它的设计目的。版本决定了能力范围,序列号保证了唯一性,签名算法和公钥信息构成了密码学基础,颁发者和主体建立了信任关系,有效期控制了风险窗口,扩展项则提供了精细的权限控制。

你可能会觉得这些字段很枯燥。但相信我,后面做证书链验证的时候,你会感谢自己现在把这些概念理清了。因为每一个验证步骤,都是在跟这些字段打交道。