2. X.509证书标准:证书结构、版本号、序列号、签名算法、颁发者与使用者、有效期、扩展域

聊到PKI,X.509证书就是那个绕不开的核心。说白了,它就是数字世界里的身份证。我刚开始接触证书时,觉得这东西就是个文件,后来踩过坑才明白——证书里的每一个字段,都有它存在的道理。

今天咱们就把X.509证书从头到脚拆一遍。你以后拿到一张证书,至少能看懂它到底在说什么。

2.1 证书的整体结构

一张X.509证书,不是简单的“公钥+签名”。它有一套标准化的结构。我习惯把它想象成一个信封:信封外面写着谁发的、发给谁、什么时候过期;信封里面装着真正的宝贝——公钥。

证书的基本结构可以分成三大部分:

  • 证书主体(TBSCertificate):包含版本、序列号、签名算法、颁发者、有效期、使用者、公钥、扩展域等。这部分是要被签名的原始数据。
  • 签名算法标识:告诉你怎么验证这个签名。
  • 签名值:CA对证书主体做的数字签名,防止篡改。

嗯,这里要注意:签名算法标识出现了两次。一次在证书主体里,一次在外面。为什么?我后面会讲。

核心原则:证书的信任基础,就是CA对TBSCertificate的签名。只要签名有效,证书里的所有信息就不可抵赖。

X.509 v3 证书结构 TBSCertificate(证书主体) 版本号 (v1/v2/v3) 序列号 (唯一标识) 签名算法 颁发者 (Issuer) 有效期 (NotBefore/NotAfter) 使用者 (Subject) 公钥信息 扩展域 (Extensions) Issuer Unique ID / Subject Unique ID (v2/v3 可选) 签名算法标识 签名值 (Signature Value)

2.2 版本号

X.509证书有三个版本。你想想看,现在谁还用v1?基本绝迹了。

版本 特点 现状
v1 (1988) 最原始的结构,没有扩展域 基本淘汰,仅兼容遗留系统
v2 (1993) 增加了颁发者和使用者唯一标识符 很少使用,被v3取代
v3 (1996) 引入扩展域,支持自定义属性 当前唯一标准

我个人习惯,在任何新项目中都只用v3。为什么?因为扩展域太重要了。没有扩展域,你就没法做SAN(主题备用名称)、没法做密钥用法限制、没法做CA标志位。说白了,v3之前的证书就是个“裸奔”的公钥。

小技巧:用OpenSSL查看证书版本时,v3证书显示的是2(从0开始计数)。别被这个数字搞懵了。

2.3 序列号

序列号是CA给每张证书分配的唯一编号。它必须唯一,不能重复。我曾经遇到过一个问题:某个CA的序列号生成器出了bug,重复了序列号。结果呢?证书吊销列表(CRL)里出现了两条相同序列号的记录,客户端直接报错。

序列号有几个关键点:

  • 唯一性:同一CA下,序列号必须唯一。
  • 不可预测性:RFC 5280建议序列号至少20位随机数,防止攻击者猜测。
  • 编码:ASN.1中是一个整数,但通常用十六进制表示。

避坑指南:我曾经见过有人把序列号设成固定值“1”,结果所有证书序列号都一样。这种证书在吊销时根本没法区分。序列号一定要随机生成,别偷懒。

2.4 签名算法

签名算法字段告诉验证者:这个签名是用什么算法算出来的。常见的组合有:

算法OID 哈希算法 签名算法 推荐度
sha256WithRSAEncryption SHA-256 RSA ⭐⭐⭐⭐⭐
ecdsa-with-SHA256 SHA-256 ECDSA ⭐⭐⭐⭐⭐
sha1WithRSAEncryption SHA-1 RSA ❌ 已废弃
md5WithRSAEncryption MD5 RSA ❌ 不安全

为什么签名算法要出现两次?我解释一下:证书主体里的签名算法是给签名者用的,告诉CA“请用这个算法签名”;外层的签名算法是给验证者用的,告诉客户端“请用这个算法验证”。虽然大多数情况下两者一致,但标准允许它们不同。嗯,实际中我很少见到不一致的情况,但设计上确实留了这个口子。

2.5 颁发者与使用者

这两个字段是证书的“发件人”和“收件人”。它们用DN(Distinguished Name,可分辨名称)来表示。

一个典型的DN长这样:

CN = www.example.com
O  = Example Inc.
OU = IT Department
C  = US
ST = California
L  = San Francisco

各字段含义:

  • CN (Common Name):通用名称。对于服务器证书,通常是域名。
  • O (Organization):组织名称。
  • OU (Organizational Unit):部门名称。
  • C (Country):国家代码,两位字母。
  • ST (State/Province):州或省。
  • L (Locality):城市或地点。

颁发者(Issuer)是签发这张证书的CA。使用者(Subject)是这张证书的持有者。对于自签名证书,Issuer和Subject是一样的。

重要提醒:浏览器现在不再依赖CN来匹配域名了。CN字段已经被SAN(主题备用名称)扩展取代。你配置证书时,域名一定要写在SAN里,光写CN没用。

2.6 有效期

有效期由两个时间戳组成:

  • Not Before:证书生效时间。
  • Not After:证书失效时间。

我建议你注意以下几点:

  1. 时间同步:证书验证依赖系统时间。如果服务器时间不准,证书可能被误判为过期或未生效。我遇到过一台NTP服务挂了的设备,所有证书验证都失败,排查了半天才发现是时间问题。
  2. 有效期长度:CA/Browser Forum现在要求公开信任的SSL证书最长398天。内部PKI我建议设1-2年,太长有安全风险,太短运维成本高。
  3. UTC时间格式:证书里的时间用UTC表示,格式是YYMMDDHHMMSSZ。注意,2050年之后这个格式会出问题(年份只有两位)。新标准已经改用GeneralizedTime了。

避坑指南:我曾经在凌晨2点做证书轮换,结果新证书的Not Before设成了当前时间,但客户端时间比服务器慢了5分钟。所有客户端都报“证书尚未生效”。从那以后,我习惯把Not Before设为当前时间的前10分钟,留个缓冲。

2.7 扩展域

扩展域是v3证书的灵魂。没有扩展域,证书就是个“哑巴公钥”。扩展域让证书有了“行为能力”——它能告诉客户端:我能做什么,不能做什么。

常见的扩展域:

扩展名称 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 列出证书适用的域名、IP地址等 非关键
CRL Distribution Points 2.5.29.31 指定CRL下载地址 非关键
Authority Information Access 1.3.6.1.5.5.7.1.1 指定CA证书下载地址和OCSP响应器地址 非关键

每个扩展都有一个“关键”(Critical)标志。如果某个扩展标记为关键,但客户端不认识这个扩展,客户端必须拒绝这张证书。如果标记为非关键,客户端可以忽略它。

我个人的经验:Basic Constraints和Key Usage一定要标记为关键。这两个扩展直接决定了证书的安全边界。其他扩展可以设为非关键,兼容性更好。

实战建议:生成CA证书时,Basic Constraints要设CA=True,Key Usage要包含keyCertSign和cRLSign。生成终端实体证书时,CA必须为False,Key Usage根据用途设置。这个搞反了,整个PKI就乱套了。

2.8 一个完整的证书示例

用OpenSSL查看一张实际证书,你能看到所有字段:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            04:00:00:00:00:01:23:45:67:89:ab:cd:ef
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, O = Example CA, CN = Example Root CA
        Validity
            Not Before: Jan  1 00:00:00 2024 GMT
            Not After : Jan  1 00:00:00 2025 GMT
        Subject: C = US, O = Example Inc., CN = www.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 Subject Alternative Name:
                DNS:www.example.com, DNS:example.com
    Signature Algorithm: sha256WithRSAEncryption
         Signature Value: ab:cd:ef:01:23:45:67:89... (签名值)

你看,从版本到签名值,每一段都有明确的意义。你拿到一张证书,按这个结构去读,就不会被一堆十六进制搞晕。

好了,X.509证书的结构就这些。理解了这个基础,后面讲证书链验证、CRL、OCSP时,你就能知道每个字段在验证过程中扮演什么角色了。