3、证书格式解析:X.509标准、PEM/DER编码、证书字段详解
说到证书格式,我见过不少运维同事在这上面栽跟头。明明证书内容是对的,就因为格式搞混了,折腾半天。今天咱们就把这块彻底理清楚。
3.1 X.509标准:证书的通用语言
X.509是个国际标准,定义了公钥证书的格式。说白了,它就是一套规则,告诉全世界「证书应该长什么样」。你想想看,如果每个厂商都用自己的格式,那不同系统之间怎么互认?
我在项目中遇到过最典型的场景:某银行对接第三方支付,两边证书都是X.509,但扩展字段的理解不一样,结果联调了整整两天。后来发现是标准版本没对齐——一个用的v3,另一个还在用v1。
X.509的三个版本:
- v1(1988年):基础版本,定义了主体、颁发者、有效期等核心字段
- v2(1993年):增加了唯一标识符,但实际用得很少
- v3(1996年至今):引入了扩展字段,支持SAN、密钥用法、CRL分发点等
现在基本都在用v3。如果你看到v1或v2的证书,那大概率是古董设备。
3.2 PEM与DER:两种编码方式
证书内容确定之后,怎么存到文件里?这就涉及到编码了。最常见的两种:PEM和DER。
| 特性 | PEM | DER |
|---|---|---|
| 格式 | Base64文本,可读 | 二进制,不可读 |
| 头尾标记 | 有(-----BEGIN CERTIFICATE-----) | 无 |
| 文件大小 | 比DER大约33% | 更紧凑 |
| 常见后缀 | .pem, .crt, .cer, .key | .der, .cer |
| 适用场景 | Web服务器、邮件客户端、脚本处理 | 嵌入式设备、Java keystore、Windows系统 |
我个人习惯:能用PEM就用PEM。为什么?因为出问题的时候,你可以直接cat出来看,DER就只能用openssl x509 -in xxx.der -inform der -text才能看。
小技巧:PEM和DER可以互相转换:
# PEM → DER
openssl x509 -in cert.pem -outform der -out cert.der
# DER → PEM
openssl x509 -in cert.der -inform der -out cert.pem
3.3 证书字段详解:一张证书里到底藏了什么?
好,现在咱们打开一张证书,看看里面到底有什么。我用openssl命令来展示:
openssl x509 -in example.crt -text -noout
输出结果很长,但核心字段就这些:
3.3.1 基础字段
- Version:版本号,通常是v3(值为2)
- Serial Number:序列号,CA颁发的唯一标识。我曾经遇到过一个坑:两个证书序列号一样,结果浏览器报证书冲突。后来发现是CA的数据库出了问题。
- Signature Algorithm:签名算法,比如sha256WithRSAEncryption
- Issuer:颁发者,也就是CA的信息
- Validity:有效期,包含Not Before和Not After
- Subject:主体,证书归属方的信息
- Subject Public Key Info:公钥信息,包含算法和公钥值
3.3.2 扩展字段(X.509 v3核心)
v3最大的改进就是扩展字段。这些字段决定了证书能干什么、不能干什么。
| 扩展名称 | OID | 作用 | 常见值 |
|---|---|---|---|
| Subject Alternative Name (SAN) | 2.5.29.17 | 指定证书适用的域名/IP | DNS:example.com, IP:192.168.1.1 |
| Key Usage | 2.5.29.15 | 定义密钥用途 | digitalSignature, keyEncipherment |
| Extended Key Usage (EKU) | 2.5.29.37 | 定义证书用途 | serverAuth, clientAuth |
| Basic Constraints | 2.5.29.19 | 标记是否为CA证书 | CA:TRUE, pathLen:0 |
| CRL Distribution Points | 2.5.29.31 | 证书吊销列表获取地址 | http://crl.example.com/ca.crl |
| Authority Information Access (AIA) | 1.3.6.1.5.5.7.1.1 | CA证书和OCSP地址 | http://ocsp.example.com |
注意:SAN字段现在非常重要。从Chrome 58开始,浏览器只认SAN里的域名,不再看Common Name(CN)了。我去年帮一个客户排查HTTPS报错,就是因为证书只填了CN,没填SAN,结果Chrome直接报「NET::ERR_CERT_COMMON_NAME_INVALID」。
3.4 证书链与信任模型
单张证书很少单独存在。它通常是一条链:
- 根证书(Root CA):自签名,信任的起点
- 中间证书(Intermediate CA):由根证书签发,用于签发终端证书
- 终端证书(Leaf/Server Cert):实际使用的证书
我画了张图,帮你理解这个结构:
嗯,这里要注意:服务器发送证书时,必须把整条链(除了根证书)都发过去。我见过太多配置只发了终端证书,结果客户端找不到中间证书,直接报错。
3.5 实操:如何查看和验证证书字段
光说不练假把式。咱们来点实际的:
# 查看证书所有字段
openssl x509 -in server.crt -text -noout
# 只查看有效期
openssl x509 -in server.crt -dates -noout
# 只查看主题
openssl x509 -in server.crt -subject -noout
# 只查看SAN
openssl x509 -in server.crt -ext subjectAltName -noout
# 验证证书链
openssl verify -CAfile ca-chain.crt server.crt
我的经验:写自动化脚本时,用-noout配合-subject、-dates这些参数,可以快速提取关键信息。比如监控证书过期时间:
end_date=$(openssl x509 -in server.crt -enddate -noout | cut -d= -f2)
echo "证书过期时间:$end_date"
3.6 常见坑与避坑指南
- 我曾经遇到过PEM文件里有多余的空格或换行,导致解析失败。解决办法:用
openssl x509 -in cert.pem -text先验证一下。 - 我曾经在Nginx里配了DER格式的证书,结果Nginx只认PEM。后来统一用PEM,省心多了。
- 我曾经看到有人把私钥和证书混在一个文件里,还以为是证书链。记住:私钥是私钥,证书是证书,别搞混。
重要提醒:永远不要用文本编辑器修改DER文件。DER是二进制的,你改一个字节,整个证书就废了。PEM可以改,但只限于换行格式,内容不能动。
证书格式这块,说白了就是三个东西:标准(X.509)、编码(PEM/DER)、字段(基础+扩展)。搞清楚了,后面配HTTPS、做证书更新,心里就有底了。