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 证书的八个核心字段串起来了。你可以看到它们之间的层级关系:
2.10 小结
X.509 证书的八个字段,每个都有它的设计目的。版本决定了能力范围,序列号保证了唯一性,签名算法和公钥信息构成了密码学基础,颁发者和主体建立了信任关系,有效期控制了风险窗口,扩展项则提供了精细的权限控制。
你可能会觉得这些字段很枯燥。但相信我,后面做证书链验证的时候,你会感谢自己现在把这些概念理清了。因为每一个验证步骤,都是在跟这些字段打交道。