i007.cc

i007.cc

优先队列-降维打击

05.价值资料

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 证书签名所用算法,如 sha256WithRSAEncryptionecdsa-with-SHA384
Issuer 颁发者(CA)的可识别名(DN),如 C=US, O=Let's Encrypt, CN=R3
Validity 有效期,包含 notBeforenotAfter
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):更细粒度用途,如 serverAuthclientAuthcodeSigningemailProtection
  • 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-----(加密),通用格式,推荐使用

五、应用场景

  1. TLS/HTTPS 服务器认证:最常见场景,服务器向客户端证明身份。
  2. TLS 客户端认证(mTLS):双向认证,客户端也持证书,常用于 API 网关、零信任架构、K8s 内部通信。
  3. 代码签名:Authenticode、Java JAR 签名,证明软件来源和完整性。
  4. S/MIME:电子邮件加密和签名。
  5. 文档签名:PDF 数字签名。
  6. 智能卡 / USB Key:存储证书和私钥,用于身份认证。
  7. 物联网设备身份:每台设备预置唯一 X.509 证书,用于设备接入认证。

六、证书验证流程(以 TLS 为例)

客户端收到服务器证书链后,典型验证步骤:
  1. 解析证书,确认格式合法。
  2. 有效期检查:当前时间在 notBefore ~ notAfter 之间。
  3. 签名验证:用上级 CA 公钥验签,逐级到根。
  4. 信任锚检查:根证书在本地信任库中。
  5. 名称校验:访问的域名匹配 SAN(或 CN)。
  6. 用途检查:EKU 包含 serverAuth,Key Usage 允许数字签名。
  7. 吊销状态检查:通过 CRL 或 OCSP 确认证书未被吊销(可选,浏览器策略不同)。
  8. 基本约束检查:中间证书必须 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"

 


八、几个容易踩的坑

  1. CN 已被 SAN 取代:现代浏览器(Chrome 58+)只看 SAN,不看 CN。签发证书必须带 SAN。
  2. 证书链顺序:TLS 握手时服务器应发送 Leaf → Intermediate → ...不包含根证书。顺序错误会导致部分客户端验证失败。
  3. PKCS#12 密码:空密码在某些系统(如 macOS)上会导入失败。
  4. 中间证书缺失:服务器只发 Leaf 不发 Intermediate,移动端 / 旧浏览器可能因没有缓存中间证书而验证失败。
  5. Key Usage 不匹配:证书用途错误(如用 CA 证书当服务器证书)会被严格客户端拒绝。
  6. 时间敏感:证书验证依赖系统时钟,时钟偏差过大会导致验证失败。

需要我深入某个方向吗?比如 证书吊销机制(CRL vs OCSP vs OCSP Stapling)mTLS 在 K8s / 服务网格中的实践、或者 从零搭建一个私有 CA 的完整流程

发表回复