X.509 证书解析详解:HTTPS 背后那张证书在说什么
证书到底解决了什么问题?
HTTPS = HTTP + TLS。TLS 解决的核心问题是:你怎么确认正在通信的服务器真的是它声称的那个,而不是中间人冒充的?
如果只靠服务器发个公钥过来,中间人完全可以截掉真正的公钥、换成自己的——你加密了,但加密给了中间人。证书就是解决这个信任问题的机制:由一个你预先信任的权威机构(CA),用它的私钥给服务器公钥”签字担保”,证明”这个公钥确实属于 example.com”。
证书解析就是把这张”担保书”拆开,看清里面写了什么、谁签的、有效期、担保哪些域名。
X.509:证书的标准格式
数字证书遵循 X.509 标准(具体是 RFC 5280)。一个 X.509 证书本质上是一段结构化数据,用 ASN.1 语法描述,再编码成二进制。核心字段:
1. 版本与序列号
- 版本:v1/v2/v3,现在都是 v3(v3 才支持扩展字段)
- 序列号:CA 给每张证书的唯一编号
2. 签名算法
CA 用什么算法签的名(如 SHA256-RSA、ECDSA-SHA256)。这张证书的签名是 RSA 还是 ECDSA,一目了然。
3. 颁发者(Issuer)
谁签的这张证书,即 CA 的身份信息(DN, Distinguished Name),如 C=US, O=Let's Encrypt, CN=R3。
4. 有效期(Validity)
Not Before 和 Not After 两个时间。证书过期是 HTTPS 报错最常见的原因——浏览器报”NET::ERR_CERT_DATE_INVALID”就是有效期出了问题。Let’s Encrypt 的证书只有 90 天有效期,强制你自动续期,减少密钥泄露窗口。
5. 主体(Subject)
这张证书属于谁。早期浏览器靠 Subject 里的 CN(Common Name)字段判断域名,如 CN=example.com。但现在靠 SAN 扩展,CN 已经退居次要(Chrome 早就忽略 CN 了)。
6. 主体公钥(Subject Public Key Info)
这是证书的核心——被担保的公钥本身,以及它的算法和长度。一张 RSA 证书这里存的就是 [[rsa]] 公钥(模数 n + 指数 e);ECDSA 证书存的是椭圆曲线点。公钥长度决定安全强度(RSA 2048、ECDSA P-256 是当前主流)。
7. 扩展(Extensions)
v3 证书的精华都在扩展里,最重要的几个:
- SAN(Subject Alternative Names):这张证书担保的所有域名列表。现代浏览器只认 SAN,不认 CN。一张证书可以担保多个域名(如
example.com+www.example.com+*.example.com通配符),全列在 SAN 里 - Basic Constraints:这张证书是不是 CA(能不能再签别人的证书)。终端证书
CA:FALSE,中间/根证书CA:TRUE - Key Usage / Extended Key Usage:公钥能用来干什么(数字签名、密钥加密、服务器认证
serverAuth、客户端认证clientAuth) - AKI/SKI:颁发者/主体的密钥标识,用于构建证书链
8. 签名(Signature)
CA 用它的私钥对前面所有字段的哈希做的签名。验证证书时,用 CA 的公钥验证这个签名——签名合法,说明证书内容没被篡改、确实出自该 CA。
PEM 和 DER:两种编码
证书数据本身是二进制(DER 编码),但传输和展示时不方便,于是有了两种常见格式:
- DER:纯二进制,
.cer/.der后缀,看不懂的二进制 - PEM:把 DER 做 Base64 编码,加上
-----BEGIN CERTIFICATE-----头尾,.pem/.crt/.cer后缀。文本格式,方便复制粘贴、邮件传输
PEM 就是 Base64 化的 DER,两者内容等价,只是编码不同。证书解析器要同时支持两种:检测到 -----BEGIN 头按 PEM 解(先去头尾、Base64 解码成 DER),否则按 DER 解。
一张 PEM 文件里还可以堆多张证书(证书链),每段一对 BEGIN/END,解析时逐段处理。
证书链与信任模型
浏览器验证一张服务器证书,不是单看这一张,而是要验证整条链,直到一个预装在系统/浏览器里的根 CA(Root CA):
服务器证书(终端)
↑ 由...签发
中间 CA 证书(Intermediate)
↑ 由...签发
根 CA 证书(Root,预装在系统里,自签名)
为什么要有中间 CA?因为根 CA 的私钥太重要,不能直接拿来每天签服务器证书(用了就增加泄露风险)。所以根 CA 签中间 CA,中间 CA 再签服务器证书。根 CA 的私钥锁在硬件里、离线保管。
验证过程:
- 服务器在 TLS 握手时发来”服务器证书 + 中间证书”(不发根,根在客户端本地)
- 客户端用中间证书的公钥验证服务器证书签名
- 用根 CA 的公钥验证中间证书签名
- 根 CA 是本地预信任的 → 信任链建立
证书解析工具能帮你看清这条链:每张证书的 Issuer 是不是上一张的 Subject、签名能不能对上。链断了(缺中间证书)是 HTTPS 部署的高频错误——浏览器报” unable to verify the first certificate”就是它。
自签名证书
自己生成密钥、自己给自己签的证书叫自签名证书。因为没有受信任 CA 担保,浏览器会报”不安全”红警告。用途:
- 内网/开发环境(如
localhost、内网 IP)的 HTTPS - 测试链路加密,不需要身份验证的场景
生产环境必须用受信任 CA 签发的证书(Let’s Encrypt 免费签发是主流选择),否则用户看到红警告就跑了。
解析一张证书能发现什么
实际排查 HTTPS 问题时,解析证书能定位一大半故障:
- 域名不匹配:访问的域名不在 SAN 列表里 → 证书配错或用了通配符覆盖不到
- 过期:Not After 已过 → 续期机制挂了
- 未生效:Not Before 还没到 → 服务器时间不对,或证书签发有误
- 链不全:只有终端证书没有中间 → 服务器没配完整证书链
- 弱算法/短密钥:RSA 1024、SHA-1 签名 → 现代浏览器拒绝
- CA 失效:颁发 CA 被吊销或不在信任库 → 信任问题
小结
X.509 证书是 CA 给服务器公钥签发的”担保书”,核心字段是主体公钥、有效期、SAN(担保的域名)和 CA 签名。PEM/DER 是同一内容的两种编码。验证证书靠的是”证书链 → 预信任根 CA”的信任传递。理解了证书结构,HTTPS 报错基本能自己定位到字段级别。证书里的公钥算法(RSA/ECDSA)原理,可以进一步看 [[rsa]] 和 [[rsa-keygen]]。