公钥密码基础(十一):数字证书、PKI 与公钥信任体系
前言
前几篇文章已经建立了公钥密码的算法基础:
- DH、ECDH 可以让双方计算共享秘密;
- RSA、ECDSA、SM2 可以生成和验证数字签名;
- 公钥和私钥通过数学关系绑定在一起。
但实际通信中还有一个更基础的问题:你拿到的公钥到底属于谁?
如果 Alice 收到一个自称属于 Bob 的公钥,仅凭“这个公钥能完成 ECDH”或“这个签名能验证”仍然无法确认它来自 Bob。攻击者可以生成自己的密钥对,把自己的公钥冒充成 Bob 的公钥。数字证书和 PKI(Public Key Infrastructure,公钥基础设施)就是围绕“把身份与公钥绑定,并让验证者能够建立信任链”构建的一整套体系。
本文介绍:
- X.509 数字证书包含什么;
- CA、根证书、中间 CA 和终端证书如何组成证书链;
- TLS 如何使用证书认证服务器并结合 ECDHE 建立会话;
- CSR、证书签发、撤销和验证分别解决什么问题;
- CTF、代码审计和故障排查中应该关注哪些证书字段。
证书不是“把公钥加密一下”,PKI 也不是一个单独算法。它是一套把公钥密码、签名、身份管理、证书策略、信任锚和生命周期管理组合起来的系统。
本文以 X.509 和 Web/TLS 场景为主线。不同企业、内网、设备和国密体系可能使用不同的证书策略和算法组合,但基本的信任链思想相同。
一、为什么需要数字证书
1.1 裸公钥无法证明身份
假设 Alice 想与 Bob 建立加密连接。Bob 把公钥 Q B Q_B QB 发给 Alice,Alice 使用它进行 ECDH:
Z = d A Q B Z=d_AQ_B Z=dAQB
如果攻击者 Mallory 在传输过程中替换 Q B Q_B QB,Alice 实际上会与 Mallory 建立共享密钥。Mallory 再与 Bob 建立另一条共享密钥,就能在两条连接之间转发和修改消息。
这个问题不是 ECDH 的数学问题,而是公钥来源认证问题。Alice 需要一种机制确认:
这个公钥确实属于 Bob,或者至少属于 Bob 所代表的域名、组织、设备或服务。
1.2 证书的基本思想
数字证书是一份由受信任签发者对“身份 + 公钥 + 使用限制”进行数字签名的声明。抽象地表示为:
Cert = Sign C A _ p r i v a t e ( subject , public key , validity , extensions , … ) \operatorname{Cert}=\operatorname{Sign}_{CA\_private}(\text{subject},\text{public key},\text{validity},\text{extensions},\ldots) Cert=SignCA_private(subject,public key,validity,extensions,…)
验证者使用 CA 的公钥检查签名。如果 CA 公钥本身已经通过操作系统、浏览器、企业配置或人工方式信任,那么验证者就可以把这种信任传递给证书中的主体公钥。
证书签名只保证证书内容没有被篡改且由对应 CA 私钥签发;它不保证主体本身永远诚实,也不保证证书颁发流程一定没有业务错误。因此 PKI 还需要审核、策略、撤销和监控。
1.3 证书不等于身份本身
证书中的 Subject、域名、组织名称或设备编号是 CA 根据某种验证流程写入的声明。验证者仍然必须按照使用场景检查:
- 当前连接的主机名是否在证书允许的名称中;
- 证书是否还在有效期;
- 用途是否允许当前操作;
- 签发者是否在信任链中;
- 私钥持有者是否真的控制对应服务。
“证书签名验证成功”只是证书验证流程中的一个环节,不等于“所有身份检查都成功”。
二、X.509 证书的结构
2.1 证书的三层结构
X.509 证书通常可以抽象成:
Certificate = tbsCertificate + signatureAlgorithm + signatureValue \operatorname{Certificate}=\operatorname{tbsCertificate}+\operatorname{signatureAlgorithm}+\operatorname{signatureValue} Certificate=tbsCertificate+signatureAlgorithm+signatureValue
其中:
tbsCertificate是待签名内容,名称来自 “to be signed”;signatureAlgorithm表示签名算法标识;signatureValue是签发者对待签名内容生成的签名。
验证者首先按照 ASN.1/DER 规则解析证书,然后使用签发者公钥验证 tbsCertificate 的签名。
2.2 常见字段
TBSCertificate 中常见字段包括:
| 字段 | 作用 |
|---|---|
| Version | 证书版本,使用扩展字段时通常为 v3 |
| Serial Number | 签发者分配的证书序列号 |
| Signature | TBSCertificate 使用的签名算法标识 |
| Issuer | 签发者名称 |
| Validity | NotBefore 和 NotAfter 有效期 |
| Subject | 证书主体名称 |
| SubjectPublicKeyInfo | 主体公钥和公钥算法 |
| Extensions | 约束、用途、名称和策略等扩展 |
| Signature | 签发者对 TBS 的数字签名 |
外层的签名算法标识通常应与 TBS 中声明的签名算法一致。解析和验证时不能只看字符串名称,还要检查算法参数、哈希算法和密钥类型是否符合策略。
2.3 SubjectPublicKeyInfo
主体公钥通常位于 SubjectPublicKeyInfo 中,它包含:
- 公钥算法标识;
- 算法参数;
- 公钥比特串。
对于 RSA,参数可能涉及模数和公钥指数;对于 ECDSA、ECDH 或 SM2,参数可能涉及曲线标识和点编码。证书中的曲线、点格式和使用方支持的算法必须匹配,不能只提取一段公钥字节就忽略算法参数。
2.4 重要扩展
Basic Constraints
BasicConstraints 用来说明证书是否可以作为 CA,以及可选的路径长度约束:
CA=true表示可以作为 CA 证书使用;CA=false或缺省通常表示终端实体证书;pathLenConstraint限制后续 CA 层级数量。
如果把终端证书误当成 CA,或者忽略路径约束,证书链验证就可能出现严重错误。
Key Usage
KeyUsage 限制密钥用途,例如:
digitalSignature:数字签名;keyEncipherment:密钥加密;keyAgreement:密钥协商;keyCertSign:签发证书;cRLSign:签发 CRL。
证书即使签名算法正确,当前用途不在 KeyUsage 允许范围内,也不应接受。
Extended Key Usage
ExtendedKeyUsage 进一步描述应用用途,例如:
- TLS 服务器认证;
- TLS 客户端认证;
- 代码签名;
- 邮件保护;
- 时间戳。
服务器证书和客户端证书通常具有不同的 EKU。验证器不能看到“证书有效”就把它用于任意协议。
Subject Alternative Name
在 TLS 主机名验证中,应重点检查 Subject Alternative Name(SAN)中的 DNS 名称或 IP 地址。现代验证逻辑通常不应只依赖旧式 Common Name。
例如,连接到 api.example.test 时,应检查该主机名是否匹配 SAN 中的允许名称,并正确处理通配符边界、大小写、国际化域名和 IP 地址编码。
Authority Key Identifier 和 Subject Key Identifier
这两个扩展可以帮助构建者匹配证书与签发者密钥,但它们不是签名本身,也不能替代真正的链验证。最终仍要使用候选签发者公钥验证证书签名。
Certificate Policies
企业和高保证场景可能通过证书策略 OID 表示签发用途、审核级别或业务约束。验证者是否强制检查策略,取决于应用和信任模型。
三、CA、根证书与证书链
3.1 根 CA
根 CA 的证书通常是自签名的:
Verify R o o t P u b l i c ( Sign R o o t P r i v a t e ( T B S ) ) = true \operatorname{Verify}_{RootPublic}(\operatorname{Sign}_{RootPrivate}(TBS))=\text{true} VerifyRootPublic(SignRootPrivate(TBS))=true
但“自签名验证成功”并不能证明根 CA 值得信任。根证书之所以成为信任锚,是因为它被预置到操作系统、浏览器、企业设备、应用配置或硬件中,或者由管理员通过安全流程导入。
因此,根信任是一个配置和治理问题,不是数学公式自动推导出来的。
3.2 中间 CA
实际体系通常不直接用根 CA 为每个网站或设备签发证书,而是:
Root CA → Intermediate CA → Leaf Certificate \text{Root CA}\rightarrow\text{Intermediate CA}\rightarrow\text{Leaf Certificate} Root CA→Intermediate CA→Leaf Certificate
根 CA 离线保护,中间 CA 负责日常签发。这样可以把在线风险限制在中间 CA;如果某个中间 CA 泄露或被错误授权,可以撤销或移除它,而不必替换所有根信任锚。
3.3 终端实体证书
终端证书通常属于:
- 网站域名;
- 服务器或客户端设备;
- 用户;
- 软件发布者;
- 邮件地址;
- 企业内部服务。
终端证书一般不应具有 CA=true 和 keyCertSign,并应通过 SAN、EKU、KeyUsage 等扩展限制用途。
3.4 证书链的签名关系
假设终端证书由中间 CA 签发,中间 CA 由根 CA 签发:
- 使用中间 CA 公钥验证终端证书;
- 使用根 CA 公钥验证中间 CA 证书;
- 检查中间 CA 的
CA=true、路径长度和keyCertSign; - 检查每张证书的有效期、撤销状态和策略;
- 检查终端证书的名称和用途;
- 确认链最终连接到本地信任库中的信任锚。
链验证不是简单地“循环验签”。它还包括名称约束、路径约束、策略、用途、时间和撤销状态检查。
3.5 为什么证书链可能有多条
证书可能包含 Authority Key Identifier,服务器也可能发送多个中间证书,信任库中还可能存在交叉签发的 CA。因此验证器可能需要在候选证书中构建一条满足策略的路径。
同一终端证书在不同设备上可能出现不同验证结果,因为:
- 信任库不同;
- 根证书版本不同;
- 系统时间不同;
- 撤销检查策略不同;
- 算法策略不同;
- 服务器发送的中间证书集合不同。
四、证书签发流程与 CSR
4.1 生成密钥对
申请者首先生成私钥和公钥:
Q = d G Q=dG Q=dG
或生成 RSA 密钥对。私钥应在申请者控制的安全环境中生成和保存,CA 通常不需要知道申请者的私钥。
4.2 生成 CSR
CSR(Certificate Signing Request,证书签名请求)通常包含:
- 申请者公钥;
- 申请的主体名称或 SAN;
- 申请属性和扩展请求;
- 申请者使用对应私钥生成的签名。
抽象地表示为:
CSR = Sign A p p l i c a n t P r i v a t e ( requested identity , public key , attributes ) \operatorname{CSR}=\operatorname{Sign}_{ApplicantPrivate}(\text{requested identity},\text{public key},\text{attributes}) CSR=SignApplicantPrivate(requested identity,public key,attributes)
CSR 的签名证明“提交者持有与申请公钥对应的私钥”,但不等于 CA 已经验证了域名、组织或个人身份。CA 仍需要执行自己的验证流程。
4.3 CA 审核与签发
CA 根据证书策略执行验证,例如:
- 域名控制验证;
- 组织信息验证;
- 个人或设备身份审核;
- 企业内部审批;
- 设备注册或硬件证明。
审核通过后,CA 把批准的身份、公钥、有效期、扩展和序列号编码为 TBS 证书,并使用 CA 私钥签名。
4.4 证书续期与密钥轮换
证书到期不一定意味着私钥泄露,但续期时应考虑是否同时轮换密钥。密钥轮换可以缩短单把私钥的暴露窗口,并避免长期使用同一密钥造成管理风险。
如果私钥疑似泄露,应立即停止使用相关证书,并根据体系的撤销流程处理,而不是等到自然过期。
五、TLS 中证书和公钥密码如何配合
5.1 证书负责认证,ECDHE 负责会话密钥
现代 TLS 通常把两个目标分开:
- 证书和签名用于证明服务器身份;
- ECDHE 用于为当前连接生成临时共享秘密;
- HKDF 等 KDF 从握手秘密派生会话密钥;
- AEAD 保护应用数据。
因此,服务器证书并不是每个数据包的加密密钥,也不是把整个网页内容直接加密。它主要用于认证握手中的公钥和签名。
5.2 简化的 TLS 握手逻辑
以基于临时椭圆曲线密钥交换的握手为例,可以抽象为:
- 客户端发送支持的协议版本、密码套件和临时公钥;
- 服务器发送证书链、临时公钥和握手签名;
- 客户端验证服务器证书链、域名、用途和有效期;
- 客户端使用证书中的公钥验证服务器对握手上下文的签名;
- 双方使用各自临时私钥和对方临时公钥计算 ECDH 共享秘密;
- 双方通过 KDF 派生握手密钥和应用数据密钥;
- 使用 Finished 消息确认双方对握手 transcript 的理解一致;
- 后续应用数据使用 AEAD 加密和认证。
证书验证失败、签名验证失败、主机名不匹配或 Finished 校验失败,都不应继续建立连接。
5.3 为什么不能关闭主机名验证
某些开发者只调用“证书签名验证”而不检查当前主机名。这样攻击者即使拿到一个由受信 CA 签发给其他域名的证书,也可能被错误接受。
完整的 TLS 客户端验证通常至少需要:
- 证书链连接到信任锚;
- 当前时间在有效期内;
- SAN 与目标主机名匹配;
- EKU 允许服务器认证;
- 签名算法和密钥强度符合策略;
- 根据策略执行撤销或状态检查;
- 握手签名和 Finished 校验成功。
六、证书撤销与生命周期
6.1 为什么需要撤销
证书在有效期内也可能失效,例如:
- 私钥泄露;
- 域名控制权改变;
- 证书错误签发;
- 设备被注销;
- 员工离职或权限撤销;
- CA 发现申请材料不真实。
撤销机制用于表达“这张证书在自然到期前已经不应再被信任”。
6.2 CRL
CRL(Certificate Revocation List)是 CA 定期签发的撤销列表,通常包含:
- 签发者;
- 更新时间和下次更新时间;
- 被撤销证书的序列号;
- 撤销时间和原因;
- CA 对 CRL 的数字签名。
验证者下载 CRL 后,根据证书序列号判断是否撤销。CRL 的缺点是体积可能较大,更新也可能不够及时。
6.3 OCSP
OCSP 允许验证者针对某张证书向状态服务查询:
- good;
- revoked;
- unknown。
它减少了传输完整 CRL 的需要,但引入了在线查询、隐私、可用性和软失败策略问题。
6.4 OCSP Stapling
在 OCSP Stapling 中,服务器预先从 CA 获取状态响应,并在 TLS 握手中发送。客户端不必直接联系 CA 的 OCSP 服务,既改善隐私,也降低连接时延,但服务器必须及时更新并正确验证 stapled response。
6.5 吊销不是万能的
不同客户端可能采用不同的撤销策略:
- 严格失败:无法查询状态就拒绝;
- 软失败:查询失败时继续连接;
- 使用短有效期证书降低依赖;
- 由应用、浏览器或企业策略额外处理。
因此,PKI 中的撤销、短周期证书、密钥轮换、监控和事件响应通常需要组合使用。
七、证书验证的完整检查框架
验证一张终端证书时,可以按以下层次排查。
7.1 编码和结构
- 是否是合法 DER/PEM;
- ASN.1 长度是否一致;
- 关键字段是否重复或异常;
- 外层和 TBS 签名算法是否符合预期;
- 公钥算法参数是否能被当前实现识别。
7.2 链和信任
- 是否能找到签发者;
- 每一级签名是否验证成功;
- 根是否在本地信任库;
- 中间证书是否标记为 CA;
- 路径长度和名称约束是否满足;
- 是否因为交叉签发出现不同链路径。
7.3 时间和状态
- 当前时间是否在
NotBefore和NotAfter之间; - 是否检查证书和中间 CA 的撤销状态;
- 系统时钟是否可信;
- 是否存在证书尚未生效或已经过期的情况。
7.4 名称和用途
- SAN 是否匹配目标主机名;
- 通配符是否只匹配允许的域名层级;
- IP 地址是否按 IP 类型匹配,而不是当作普通字符串;
- EKU 是否包含所需用途;
- KeyUsage 是否允许当前操作;
- 是否误把客户端证书当作服务器证书。
7.5 密钥和算法策略
- RSA 模数、ECC 曲线和密钥长度是否满足策略;
- 签名哈希和公钥算法是否已被禁止;
- 是否存在弱参数、过时算法或不支持的曲线;
- 证书中的公钥是否与实际服务端私钥匹配。
八、CTF 与代码审计中的证书排查
8.1 用 OpenSSL 查看证书
在授权的离线环境中,可以先查看证书概要:
openssl x509 -in server.crt -text -noout
重点观察:
Issuer和Subject;Validity;Subject Public Key Info;X509v3 extensions;Subject Alternative Name;Key Usage和Extended Key Usage;Basic Constraints;- 签名算法和序列号。
8.2 验证证书链
已知根证书和中间证书时,可以使用:
openssl verify \
-CAfile root-ca.crt \
-untrusted intermediate-ca.crt \
server.crt
命令成功不代表应用层所有检查都已完成。还要单独确认主机名、用途、时间和应用策略。
8.3 检查公钥是否匹配私钥
对 RSA,可以比较模数摘要;对 ECC,可以比较公钥点编码。抽象关系是:
Q c e r t i f i c a t e = ? PublicKey ( d s e r v e r ) Q_{certificate}\stackrel{?}=\operatorname{PublicKey}(d_{server}) Qcertificate=?PublicKey(dserver)
如果证书公钥和服务端私钥不匹配,握手签名会失败。生产排障中,证书文件、私钥文件和中间链文件经常来自不同部署版本,这是常见故障来源。
8.4 证书题的常见考点
CTF 或审计题可能利用:
- 证书过期但验证器忽略时间;
- 主机名不匹配但客户端关闭校验;
- 伪造的自签名根被错误导入信任库;
CA=true、keyCertSign等约束处理错误;- 使用错误的证书链或交叉签发路径;
- 弱 RSA 密钥、重复素因子或错误 ECC 参数;
- 只验证证书签名,不验证链和用途;
- 解析器对 SAN、通配符或 ASN.1 边界处理不一致。
排查时应先明确程序实际验证了哪些字段,不要默认“调用了 verify 函数”就代表完成了完整 PKI 验证。
九、PKI 的信任边界与常见攻击面
9.1 信任任何证书
开发环境中常见的“跳过证书验证”“信任所有根”“忽略主机名”会把攻击者的自签名证书直接变成有效身份。测试开关不能进入生产环境,也不能通过环境变量在不知情的情况下改变安全策略。
9.2 信任锚管理错误
根证书一旦进入信任库,通常可以签发或验证该信任域内的大量证书。因此:
- 不应把测试根证书部署到生产设备;
- 企业根证书应有明确的导入、审计和退出流程;
- 不同业务域不应无边界共享根信任;
- 应及时删除失效或被滥用的信任锚。
9.3 证书链不等于授权
证书可能证明“某个域名的私钥持有者”,但并不自动证明该主体可以访问某个 API、数据库或管理操作。应用层仍需要用户认证、授权、访问控制和审计。mTLS 证书可以作为客户端身份的一部分,但不能替代业务权限模型。
9.4 私钥保护是 PKI 的核心
CA 体系、证书链和算法都正确,如果终端私钥被复制,攻击者仍然可以冒充主体。高价值 CA 和设备私钥通常需要:
- HSM 或安全密钥存储;
- 访问控制和双人审批;
- 密钥备份与恢复策略;
- 审计日志;
- 证书生命周期自动化;
- 泄露后的撤销和轮换预案。
十、数字证书与公钥密码的关系
可以把整个体系分成四层:
10.1 数学层
RSA、ECDH、ECDSA、SM2 等提供模幂、点乘、签名和密钥交换等数学原语。
10.2 协议层
TLS、S/MIME、IPsec、设备注册协议等规定如何交换公钥、签名握手、派生密钥和保护数据。
10.3 证书层
X.509 证书把身份、公钥、有效期和用途编码起来,由 CA 进行签名。
10.4 治理层
PKI 还包括:
- 谁可以申请证书;
- CA 如何验证身份;
- 哪些根证书受信;
- 证书多久过期;
- 私钥如何生成和保存;
- 泄露后如何撤销和轮换;
- 谁负责审计和事件响应。
安全事故经常发生在协议和治理层,而不是底层椭圆曲线公式本身。理解这四层,才能看清“证书验证成功”到底说明了什么、没有说明什么。
十一、常见误区
11.1 证书是公钥的加密版本
错误。证书通常是 CA 对包含公钥和身份信息的结构进行数字签名,不是把公钥加密后交给验证者。
11.2 证书签名验证成功就一定安全
错误。还要检查信任链、时间、域名、用途、撤销、算法策略和私钥使用情况。
11.3 Subject 中写了域名就等于主机名匹配
不一定。TLS 主机名验证应按协议和库的规则检查 SAN,不能只读取任意文本字段。
11.4 根证书自签名证明它可信
错误。根证书是信任锚,可信性来自安全配置和治理流程,而不是来自自签名本身。
11.5 证书能替代访问控制
错误。证书可以表达身份或密钥持有关系,但应用仍必须执行授权、最小权限和审计。
11.6 关闭验证只是开发问题
错误。测试代码、调试参数和“临时绕过”一旦进入生产,就会把中间人攻击直接变成可行攻击。
十二、总结
数字证书解决的是“公钥属于谁”的问题,PKI 则把这个问题扩展成一套完整的信任和生命周期体系。
X.509 证书可以抽象为:
Cert = Sign C A _ p r i v a t e ( 身份 , 公钥 , 有效期 , 用途 , 扩展 ) \operatorname{Cert}=\operatorname{Sign}_{CA\_private}(\text{身份},\text{公钥},\text{有效期},\text{用途},\text{扩展}) Cert=SignCA_private(身份,公钥,有效期,用途,扩展)
验证者需要从终端证书一路构建到本地信任锚,并检查:
- 每级证书签名;
- CA 约束和路径长度;
- 有效期和撤销状态;
- SAN、KeyUsage 和 EKU;
- 算法与密钥策略;
- 当前服务是否真的持有证书对应私钥。
在 TLS 等协议中,证书主要负责身份认证,ECDHE 等算法负责建立临时共享秘密,KDF 派生会话密钥,AEAD 保护应用数据。证书不是单独完成所有安全目标的魔法文件,而是公钥密码、协议和组织信任共同组成的一个环节。
到这里,公钥密码基础系列已经从有限域、RSA、离散对数、ECC、ECDH、ECDSA 和 SM2,延伸到了实际系统中的证书和信任体系。后续学习 TLS、代码签名、mTLS、设备身份和企业 PKI 时,都可以沿着“密钥—签名—证书—信任—生命周期”这条主线继续展开。
:数字证书、PKI 与公钥信任体系&spm=1001.2101.3001.5002&articleId=164127365&d=1&t=3&u=6775e43ec26a4871adc0a87bb30b76e5)
2812

被折叠的 条评论
为什么被折叠?



