X.509 证书标准详解
一、是什么
X.509 是 ITU-T 制定的公钥证书(Public Key Certificate)格式标准,最早是 X.500 目录服务体系的一部分,当前广泛使用的是 v3 版本(RFC 5280)。它的核心作用是:把一个公钥与一个身份(主体)通过数字签名绑定起来,从而解决 “公钥到底属于谁” 的信任问题。
一句话:X.509 证书 = 身份信息 + 公钥 + CA 的数字签名。
二、证书结构(ASN.1 DER 编码)
一张 X.509 v3 证书包含以下字段:
表格
| 字段 | 说明 |
|---|---|
| Version | 版本号,v3 对应值为 2 |
| Serial Number | CA 分配的唯一序列号,用于吊销等场景 |
| Signature Algorithm | 证书签名所用算法,如 sha256WithRSAEncryption、ecdsa-with-SHA384 |
| Issuer | 颁发者(CA)的可识别名(DN),如 C=US, O=Let's Encrypt, CN=R3 |
| Validity | 有效期,包含 notBefore 和 notAfter |
| Subject | 证书主体的 DN,如 CN=example.com;自签名证书中 Issuer = Subject |
| Subject Public Key Info | 主体公钥 + 算法标识(RSA/ECDSA/Ed25519 等) |
| Issuer Unique ID | v2 引入,已不推荐使用 |
| Subject Unique ID | 同上 |
| Extensions | v3 扩展,是现代证书的核心 |
关键 v3 扩展
- Subject Alternative Name (SAN):主体备用名,可包含多个域名、IP、邮箱。现代 TLS 证书中 SAN 是必填项,
CN字段已基本被 SAN 取代。 - Key Usage:限定公钥用途(数字签名、密钥加密、数据加密、证书签名、CRL 签名等)。
- Extended Key Usage (EKU):更细粒度用途,如
serverAuth、clientAuth、codeSigning、emailProtection。 - Basic Constraints:标识是否为 CA 证书(
CA:TRUE),以及路径长度限制。 - Authority Key Identifier (AKI):指向颁发者公钥,用于构建证书链。
- Subject Key Identifier (SKI):主体公钥的哈希标识。
- CRL Distribution Points:证书吊销列表(CRL)下载地址。
- Authority Information Access (AIA):包含 OCSP 地址和上级 CA 证书下载地址(
caIssuers)。 - Name Constraints:CA 证书中用于限定可签发的名称范围(重要的安全约束)。
三、PKI 信任体系
X.509 本身只定义格式,信任由 PKI(Public Key Infrastructure) 体系提供:
plaintext
根 CA (Root CA) ──自签名── 信任锚,预置在操作系统/浏览器中
│
└── 中间 CA (Intermediate CA) ──由根签名── 实际用于签发终端证书
│
└── 终端证书 (End-Entity / Leaf) ──由中间 CA 签名── 服务器/用户/代码
证书链验证:客户端拿到 Leaf 证书后,逐级向上验证签名,直到命中本地信任库中的 Root CA。任何一级签名失败、过期、被吊销,验证即不通过。
为什么用中间 CA?根 CA 密钥长期离线保存,中间 CA 在线签发,降低根密钥泄露风险;同时中间 CA 可被快速吊销轮换。
四、常见文件格式
X.509 证书在实际使用中有多种封装格式,这是最容易混淆的部分:
表格
| 格式 | 扩展名 | 编码 | 说明 |
|---|---|---|---|
| DER | .cer .crt .der |
二进制 | ASN.1 DER 原始编码,单张证书 |
| PEM | .pem .crt .cer |
Base64 文本 | DER 的 Base64 编码,带 -----BEGIN CERTIFICATE----- 头尾,可串联多张 |
| PKCS#7 | .p7b .p7c |
二进制 / Base64 | 可包含证书链(不含私钥),Windows 环境常见 |
| PKCS#12 | .pfx .p12 |
二进制 | 同时包含证书链和私钥,通常有密码保护 |
另外私钥格式:
- PKCS#1:
-----BEGIN RSA PRIVATE KEY-----,仅 RSA - PKCS#8:
-----BEGIN PRIVATE KEY-----(明文)或-----BEGIN ENCRYPTED PRIVATE KEY-----(加密),通用格式,推荐使用
五、应用场景
- TLS/HTTPS 服务器认证:最常见场景,服务器向客户端证明身份。
- TLS 客户端认证(mTLS):双向认证,客户端也持证书,常用于 API 网关、零信任架构、K8s 内部通信。
- 代码签名:Authenticode、Java JAR 签名,证明软件来源和完整性。
- S/MIME:电子邮件加密和签名。
- 文档签名:PDF 数字签名。
- 智能卡 / USB Key:存储证书和私钥,用于身份认证。
- 物联网设备身份:每台设备预置唯一 X.509 证书,用于设备接入认证。
六、证书验证流程(以 TLS 为例)
客户端收到服务器证书链后,典型验证步骤:
- 解析证书,确认格式合法。
- 有效期检查:当前时间在
notBefore~notAfter之间。 - 签名验证:用上级 CA 公钥验签,逐级到根。
- 信任锚检查:根证书在本地信任库中。
- 名称校验:访问的域名匹配 SAN(或 CN)。
- 用途检查:EKU 包含
serverAuth,Key Usage 允许数字签名。 - 吊销状态检查:通过 CRL 或 OCSP 确认证书未被吊销(可选,浏览器策略不同)。
- 基本约束检查:中间证书必须
CA:TRUE,Leaf 必须CA:FALSE。
七、常用 OpenSSL 命令
bash
# 查看证书内容(文本形式) openssl x509 -in cert.pem -text -noout # 查看证书的 SAN 和有效期 openssl x509 -in cert.pem -noout -ext subjectAltName -dates # DER 转 PEM openssl x509 -inform DER -in cert.cer -out cert.pem # PEM 转 DER openssl x509 -outform DER -in cert.pem -out cert.cer # 从 PFX 提取证书(不含私钥) openssl pkcs12 -in cert.pfx -clcerts -nokeys -out cert.pem # 从 PFX 提取私钥(PKCS#8 加密格式) openssl pkcs12 -in cert.pfx -nocerts -out key.pem # 验证证书链 openssl verify -CAfile chain.pem cert.pem # 连接远程服务器查看证书链 openssl s_client -connect example.com:443 -showcerts # 生成自签名证书(RSA 2048,有效期 365 天) openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem \ -days 365 -nodes -subj "/CN=localhost" \ -addext "subjectAltName=DNS:localhost,IP:127.0.0.1" # 生成 ECDSA 自签名证书(更轻量) openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \ -keyout key.pem -out cert.pem -days 365 -nodes \ -subj "/CN=localhost"
八、几个容易踩的坑
- CN 已被 SAN 取代:现代浏览器(Chrome 58+)只看 SAN,不看 CN。签发证书必须带 SAN。
- 证书链顺序:TLS 握手时服务器应发送
Leaf → Intermediate → ...,不包含根证书。顺序错误会导致部分客户端验证失败。 - PKCS#12 密码:空密码在某些系统(如 macOS)上会导入失败。
- 中间证书缺失:服务器只发 Leaf 不发 Intermediate,移动端 / 旧浏览器可能因没有缓存中间证书而验证失败。
- Key Usage 不匹配:证书用途错误(如用 CA 证书当服务器证书)会被严格客户端拒绝。
- 时间敏感:证书验证依赖系统时钟,时钟偏差过大会导致验证失败。
需要我深入某个方向吗?比如 证书吊销机制(CRL vs OCSP vs OCSP Stapling)、mTLS 在 K8s / 服务网格中的实践、或者 从零搭建一个私有 CA 的完整流程。
