PKI与数字证书详解
HTTPS 握手失败报「证书不受信任」、.pem 和 .crt 分不清、文档里同时出现 PKI、X.509、CA、Trust Store——这些名词往往指向同一条 「如何证明公钥属于某个身份」 的链路。下面从公钥密码学出发,说明 X.509 证书结构、PEM/DER 编码、PKI 信任链,以及 TLS 里如何验证书;文末附术语速查与常见文件头标记。
目录
- 1. 证书解决什么问题
- 2. 公钥与私钥
- 3. X.509:证书的标准格式
- 4. PEM、DER 与常见扩展名
- 5. PKI 与证书链
- 5.3 证书路径构建与交叉签名
- 6. TLS 握手里的验链流程
- 6.1 Key Usage 与 Extended Key Usage
- 6.2 RSA 与 ECDSA 在 TLS 中的差异
- 7. 公网 PKI 与私有 PKI
- 8. 常见 PEM 块类型
- 9. 延伸阅读与落地注意
- 10. 术语速查表
1. 证书解决什么问题
两台程序要通过网络 加密通信(HTTPS、MQTT over TLS、gRPC with TLS 等),通常需要同时满足:
| 机密性 | 截获流量也无法读懂明文 |
| 完整性 | 数据途中被篡改可被察觉 |
| 身份认证 | 确认对端确实是预期的服务器或客户端,而非中间人 |
非对称加密(公钥 / 私钥)提供加密与签名的数学基础,但单独一个公钥无法回答:「这个公钥真的属于 example.com 吗?」
数字证书把 身份(Subject)、公钥、签发者(Issuer)、有效期 和 数字签名 绑在一起,形成可被第三方验证的声明。验证方只要信任签发该证书的 CA,就能间接信任证书里的公钥。
2. 公钥与私钥
非对称算法(RSA、ECDSA、Ed25519 等)生成 密钥对:
| 是否公开 | 可公开分发 | 必须严格保密 |
| 典型用途 | 加密发给对方的数据;验证对方签名 | 解密;生成数字签名 |
| 丢失后果 | 重新分发即可 | 身份冒充、解密历史密文(视场景而定) |
在 TLS 中,服务器证书里的公钥常用于密钥交换阶段;私钥永远只留在证书主体一侧(服务器、设备或 HSM),不应出现在客户端安装包、公开仓库或日志里。
3. X.509:证书的标准格式
X.509 不是文件后缀,而是 ITU-T 标准,规定 数字证书应包含哪些字段、如何编码。绝大多数 TLS 证书都是 X.509 v3。
一张 X.509 证书的核心字段:
| Subject | 证书主体(发给谁) | CN=*.example.com, O=Example Inc |
| Issuer | 签发者 | CN=Example Intermediate CA, O=Example CA |
| Subject Public Key Info | 主体的公钥及算法 | RSA 2048 / ECDSA P-256 |
| Validity | 生效与过期时间 | Not Before / Not After |
| Extensions | 扩展用途 | Subject Alternative Name(SAN)、Basic Constraints(是否 CA) |
| Signature | 签发者用 私钥 对证书 TBSCertificate 部分的签名 | 证明 Issuer 认可该证书内容 |
逻辑结构示意:
┌─────────────────────────────────────────┐
│ X.509 证书 │
├─────────────────────────────────────────┤
│ Version, Serial Number │
│ Signature Algorithm │
│ Issuer(谁签的) │
│ Validity(有效期) │
│ Subject(发给谁) │
│ Subject Public Key Info(公钥 + 算法) │
│ Extensions(SAN、keyUsage、isCA 等) │
│ ───────────────────────────────────── │
│ Signature(Issuer 私钥签名) │
└─────────────────────────────────────────┘
小结: 说「这是一张 X.509 证书」= 其 语义与二进制结构 符合 X.509;与磁盘上是 .pem 还是 .der 无关。
3.1 Key Usage 与 Extended Key Usage(预览)
证书 能用来干什么,由扩展字段约束;TLS 验链时会检查 用途是否匹配当前角色(详见 §6.1)。
| keyUsage | digitalSignature | 允许用证书私钥做 TLS 握手签名(CertificateVerify 等) |
| keyUsage | keyEncipherment(RSA)/ 常与 ECDSA 组合策略不同 | RSA 场景下可用于 密钥传输/封装;ECDSA 叶子通常以 digitalSignature 为主 |
| Extended Key Usage(EKU) | id-kp-serverAuth | 允许作为 TLS 服务端 身份证书 |
| Extended Key Usage(EKU) | id-kp-clientAuth | 允许作为 TLS 客户端 身份证书(mTLS) |
CA 证书则在 Basic Constraints 中标记 CA:TRUE,并限制 keyCertSign 等,与叶子用途严格区分。
4. PEM、DER 与常见扩展名
同一张 X.509 证书可以用不同 编码方式 存盘:
| DER | Distinguished Encoding Rules | 二进制 ASN.1 编码;体积小,不适合直接文本编辑 |
| PEM | Privacy-Enhanced Mail | 对 DER 做 Base64,外加 —–BEGIN …—– / —–END …—– 头尾;文本可读,便于配置与版本管理 |
| .crt / .cer | 常见扩展名 | 内容可能是 PEM 或 DER,看文件内容而非后缀 |
| .pem | 常见扩展名 | 多为 PEM 文本;也可能包含证书、私钥、证书链等多段块 |
PEM 证书典型外观:
—–BEGIN CERTIFICATE—–
MIIDQTCCAimgAwIBAgITBmyfz5m/joaD2…
(Base64 行)
…
—–END CERTIFICATE—–
解码 Base64 后得到的是 DER 编码的 X.509 证书。
#mermaid-svg-HnXUlcUVtEpwNCAI{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HnXUlcUVtEpwNCAI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HnXUlcUVtEpwNCAI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HnXUlcUVtEpwNCAI .error-icon{fill:#552222;}#mermaid-svg-HnXUlcUVtEpwNCAI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HnXUlcUVtEpwNCAI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HnXUlcUVtEpwNCAI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HnXUlcUVtEpwNCAI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HnXUlcUVtEpwNCAI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HnXUlcUVtEpwNCAI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HnXUlcUVtEpwNCAI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HnXUlcUVtEpwNCAI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HnXUlcUVtEpwNCAI .marker.cross{stroke:#333333;}#mermaid-svg-HnXUlcUVtEpwNCAI svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HnXUlcUVtEpwNCAI p{margin:0;}#mermaid-svg-HnXUlcUVtEpwNCAI .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-HnXUlcUVtEpwNCAI .cluster-label text{fill:#333;}#mermaid-svg-HnXUlcUVtEpwNCAI .cluster-label span{color:#333;}#mermaid-svg-HnXUlcUVtEpwNCAI .cluster-label span p{background-color:transparent;}#mermaid-svg-HnXUlcUVtEpwNCAI .label text,#mermaid-svg-HnXUlcUVtEpwNCAI span{fill:#333;color:#333;}#mermaid-svg-HnXUlcUVtEpwNCAI .node rect,#mermaid-svg-HnXUlcUVtEpwNCAI .node circle,#mermaid-svg-HnXUlcUVtEpwNCAI .node ellipse,#mermaid-svg-HnXUlcUVtEpwNCAI .node polygon,#mermaid-svg-HnXUlcUVtEpwNCAI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HnXUlcUVtEpwNCAI .rough-node .label text,#mermaid-svg-HnXUlcUVtEpwNCAI .node .label text,#mermaid-svg-HnXUlcUVtEpwNCAI .image-shape .label,#mermaid-svg-HnXUlcUVtEpwNCAI .icon-shape .label{text-anchor:middle;}#mermaid-svg-HnXUlcUVtEpwNCAI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HnXUlcUVtEpwNCAI .rough-node .label,#mermaid-svg-HnXUlcUVtEpwNCAI .node .label,#mermaid-svg-HnXUlcUVtEpwNCAI .image-shape .label,#mermaid-svg-HnXUlcUVtEpwNCAI .icon-shape .label{text-align:center;}#mermaid-svg-HnXUlcUVtEpwNCAI .node.clickable{cursor:pointer;}#mermaid-svg-HnXUlcUVtEpwNCAI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HnXUlcUVtEpwNCAI .arrowheadPath{fill:#333333;}#mermaid-svg-HnXUlcUVtEpwNCAI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HnXUlcUVtEpwNCAI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HnXUlcUVtEpwNCAI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HnXUlcUVtEpwNCAI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HnXUlcUVtEpwNCAI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HnXUlcUVtEpwNCAI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HnXUlcUVtEpwNCAI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HnXUlcUVtEpwNCAI .cluster text{fill:#333;}#mermaid-svg-HnXUlcUVtEpwNCAI .cluster span{color:#333;}#mermaid-svg-HnXUlcUVtEpwNCAI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HnXUlcUVtEpwNCAI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HnXUlcUVtEpwNCAI rect.text{fill:none;stroke-width:0;}#mermaid-svg-HnXUlcUVtEpwNCAI .icon-shape,#mermaid-svg-HnXUlcUVtEpwNCAI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HnXUlcUVtEpwNCAI .icon-shape p,#mermaid-svg-HnXUlcUVtEpwNCAI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HnXUlcUVtEpwNCAI .icon-shape .label rect,#mermaid-svg-HnXUlcUVtEpwNCAI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HnXUlcUVtEpwNCAI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HnXUlcUVtEpwNCAI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HnXUlcUVtEpwNCAI :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
编码层
逻辑层
X.509 证书结构
DER 二进制 ASN.1
PEM Base64 文本
易混点:
- X.509 → 证书 是什么(标准格式)
- DER / PEM → 证书 怎么存(编码)
- 证书 ≠ 裸公钥:裸公钥文件缺少 Issuer、有效期、用途扩展等,不能单独构成 PKI 信任链
5. PKI 与证书链
PKI(Public Key Infrastructure,公钥基础设施)指 围绕数字证书的一整套制度与技术:根 CA、中间 CA、签发流程、吊销、策略、审计与信任分发等。PKI 不是单个文件,而是 体系。
5.1 CA 层级
典型三级模型:
┌─────────────────────┐
│ Root CA(根 CA) │ 自签名;离线或 HSM 保护
└──────────┬──────────┘
│ 根 CA 私钥签发
┌──────────▼──────────┐
│ Intermediate CA │ 日常签发;可多个
└──────────┬──────────┘
│ 中间 CA 私钥签发
┌──────────▼──────────┐
│ End Entity(叶子) │ 服务器 / 设备 / 客户端
│ CN=api.example.com │
└─────────────────────┘
| Root CA | 根证书 + 根 私钥 | 信任锚;只用来签中间 CA,少上线 |
| Intermediate CA | 中间证书 + 中间私钥 | 批量签发叶子证书 |
| Leaf / End Entity | 实体证书 + 实体 私钥 | TLS 握手时 出示 给对端 |
5.2 证书链(Chain of Trust)
对端在 TLS 握手中可能发送 多张证书:叶子 + 若干中间 CA。验证方从叶子出发,用 Issuer 的公钥(来自上一级证书)逐级验证签名,直到链接到 本地信任的根 CA。
验证逻辑(简化):
fullchain.pem 一类文件常把 叶子 + 中间 CA 顺序拼接,便于 Web 服务器配置;根 CA 通常不必发送(客户端 Trust Store 里已有)。
5.3 证书路径构建与交叉签名
实际验链时,客户端做的不是「按发送顺序线性往上验」这么简单,而是 证书路径构建(certification path building):
- 握手包里的证书 + 本地 Trust Store +(必要时)AIA(Authority Information Access)扩展中给出的 Issuer URL,共同构成候选图
- 验证器要在图中找到 至少一条 从叶子到 受信任根 的合法路径;可能存在 多条可行路径(交叉签名场景)
交叉签名(cross-signing) 典型例子:Let’s Encrypt 的 R3 中间 CA 曾同时由 ISRG Root X1 与旧 DST Root CA X3 交叉签发,以便在旧系统 Trust Store 未更新时仍能验链。不同客户端 Trust Store 版本不同,同一张叶子 可能走不同路径——排查「有的机器能连、有的不能」时,应对比 完整链与本地根库。
证书 Authority Information Access 扩展可含 caIssuers URL,验证器缺中间 CA 时可 主动拉取(有隐私与可用性权衡;生产环境仍建议服务端发送完整链)。
6. TLS 握手里的验链流程
以客户端访问 HTTPS 为例(单向 TLS,最常见):
服务器
客户端
服务器
客户端
#mermaid-svg-zUtEscOLLxdLeBpS{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zUtEscOLLxdLeBpS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zUtEscOLLxdLeBpS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zUtEscOLLxdLeBpS .error-icon{fill:#552222;}#mermaid-svg-zUtEscOLLxdLeBpS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zUtEscOLLxdLeBpS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zUtEscOLLxdLeBpS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zUtEscOLLxdLeBpS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zUtEscOLLxdLeBpS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zUtEscOLLxdLeBpS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zUtEscOLLxdLeBpS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zUtEscOLLxdLeBpS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zUtEscOLLxdLeBpS .marker.cross{stroke:#333333;}#mermaid-svg-zUtEscOLLxdLeBpS svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zUtEscOLLxdLeBpS p{margin:0;}#mermaid-svg-zUtEscOLLxdLeBpS .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-zUtEscOLLxdLeBpS text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-zUtEscOLLxdLeBpS .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-zUtEscOLLxdLeBpS .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-zUtEscOLLxdLeBpS .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-zUtEscOLLxdLeBpS .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-zUtEscOLLxdLeBpS #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-zUtEscOLLxdLeBpS .sequenceNumber{fill:white;}#mermaid-svg-zUtEscOLLxdLeBpS #sequencenumber{fill:#333;}#mermaid-svg-zUtEscOLLxdLeBpS #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-zUtEscOLLxdLeBpS .messageText{fill:#333;stroke:none;}#mermaid-svg-zUtEscOLLxdLeBpS .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-zUtEscOLLxdLeBpS .labelText,#mermaid-svg-zUtEscOLLxdLeBpS .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-zUtEscOLLxdLeBpS .loopText,#mermaid-svg-zUtEscOLLxdLeBpS .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-zUtEscOLLxdLeBpS .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-zUtEscOLLxdLeBpS .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-zUtEscOLLxdLeBpS .noteText,#mermaid-svg-zUtEscOLLxdLeBpS .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-zUtEscOLLxdLeBpS .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-zUtEscOLLxdLeBpS .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-zUtEscOLLxdLeBpS .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-zUtEscOLLxdLeBpS .actorPopupMenu{position:absolute;}#mermaid-svg-zUtEscOLLxdLeBpS .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-zUtEscOLLxdLeBpS .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-zUtEscOLLxdLeBpS .actor-man circle,#mermaid-svg-zUtEscOLLxdLeBpS line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-zUtEscOLLxdLeBpS :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
用 Trust Store 中的根/中间 CA 验链
检查 hostname、有效期、吊销策略
ClientHello
ServerHello + 证书链(叶子 + 中间 CA)
密钥交换 + Finished(后续流量加密)
客户端侧关键步骤:
| 1 | 解析服务器发来的 DER/PEM 证书链 |
| 2 | 自底向上验证每张证书的签名 |
| 3 | 根 CA 必须落在 系统或应用 Trust Store |
| 4 | 检查 hostname(SAN/CN)是否与 URL 一致 |
| 5 | 可选:吊销检查(OCSP/CRL)、Certificate Transparency 等 |
吊销与 OCSP Stapling: 除 Trust Store 验链外,客户端可查询 OCSP 或 CRL 确认证书未被吊销。为减少延迟与隐私泄露(客户端直连 OCSP Responder 会暴露访问行为),生产 HTTPS 常启用 OCSP Stapling:服务器在 TLS 握手中附带 由 CA 签名的 OCSP 响应,客户端本地校验该 stapled 响应即可,无需再发额外 OCSP 请求。
mTLS(双向 TLS) 在以上基础上,服务器还要求客户端出示 客户端证书,并用服务器侧 Trust Store 验证——常见于 Zero Trust、设备管理、部分 IoT 与金融接口。
6.1 Key Usage 与 Extended Key Usage
RFC 5280 将 密钥用途 分为两层,验链时与「这张证能不能用于 TLS 服务端/客户端」直接相关:
| keyUsage | 公钥允许的操作类型 | digitalSignature(必须,用于握手签名);RSA 还常见 keyEncipherment(旧式 RSA 密钥交换) |
| extendedKeyUsage(EKU) | 扩展用途 OID | 含 id-kp-serverAuth(即常说的 serverAuth) |
中间 CA 通常具备 keyCertSign + cRLSign(在 keyUsage 中),不应 同时带 serverAuth EKU 去冒充叶子。客户端库(OpenSSL、BoringSSL、平台 Network Security)会在 path validation 阶段执行上述检查;配置错误(如叶子缺 EKU)会导致 握手失败但签名本身有效 的迷惑现象。
OpenSSL 查看扩展:
openssl x509 -in server.crt -noout -ext keyUsage,extendedKeyUsage,basicConstraints
6.2 RSA 与 ECDSA 在 TLS 中的差异
证书 Subject Public Key Info 里的算法类型,影响握手性能与 cipher 搭配,而非仅「签名算法名字不同」:
| 密钥长度 | 常见 2048/4096 bit,证书与运算较重 | P-256 / P-384 等等价安全强度下 更短、更快 |
| keyUsage 侧重 | 常同时见 digitalSignature + keyEncipherment | 叶子以 digitalSignature 为主 |
| TLS 1.3 | 仍可用;密钥交换走 (EC)DHE,证书主要用于 身份签名 | 主流选型,握手包更小 |
| TLS 1.2 遗留 | 部分旧 cipher 套件曾用 RSA 直接做密钥传输(已逐步淘汰) | 依赖 ECDHE 等临时密钥交换 |
选型上,新部署 优先 ECDSA(或 Ed25519,视 CA 与客户端支持) 即可;排查兼容性时同时看 叶子算法、中间 CA 签名算法、Trust Store 是否信任对应根。
7. 公网 PKI 与私有 PKI
| 根 CA 示例 | DigiCert、Let’s Encrypt ISRG Root | 企业自建 Root CA |
| 信任来源 | 操作系统、浏览器 预装 | 应用或设备 内置 CA 证书 |
| 典型场景 | 公网网站、SaaS API | 内网服务、设备直连、离线环境 |
| Leaf 签发 | 公有 CA 或 ACME 自动化 | 内部 CA 或出厂预置 |
私有 PKI 下,若客户端 不 内置对应根/中间 CA,TLS 会因 UNKNOWN CA 失败。因此 IoT 网关、企业 App、嵌入式 Agent 常在资源目录或配置里附带 CA 证书 PEM,运行时注入自定义 SSLContext / TrustManager(各语言 API 不同,原理一致)。
这与 Certificate Pinning(证书固定) 不同:
| 内置 CA | 信任某一 签发机构 签出的所有合规证书 | 适配私有 PKI、内网 |
| Pinning | 固定 某一叶子或 SPKI 公钥哈希 | 防 rogue CA、强防中间人;轮换成本高 |
8. 常见 PEM 块类型
打开 .pem 文件时,根据 BEGIN 行判断内容:
| BEGIN CERTIFICATE | X.509 证书(CA 或实体) | CA/实体 公钥证书 可公开 |
| BEGIN CERTIFICATE REQUEST | CSR:申请证书时提交 | 可公开 |
| BEGIN PUBLIC KEY / BEGIN RSA PUBLIC KEY | 裸公钥 | 可公开 |
| BEGIN PRIVATE KEY | PKCS#8 等格式 私钥 | 绝不可公开 |
| BEGIN RSA PRIVATE KEY | 传统 RSA 私钥 | 绝不可公开 |
| BEGIN ENCRYPTED PRIVATE KEY | 口令保护的私钥 | 仍属敏感材料 |
运维检查清单:
- 仓库、镜像、客户端包里 不应 出现 PRIVATE KEY 块
- 服务器只需配置 证书 + 私钥;客户端通常只需 CA 或 pin 策略
- 合并链时注意顺序:叶子在前,根 CA 一般不发给对端
命令行快速查看证书(OpenSSL):
# 查看 PEM 证书 Subject / Issuer / 有效期
openssl x509 -in server.crt -noout -subject -issuer -dates
# 查看 SAN、密钥用途
openssl x509 -in server.crt -noout -ext subjectAltName,keyUsage,extendedKeyUsage
# 验证文件是否为合法 DER/PEM 证书
openssl x509 -in server.crt -inform PEM -noout
9. 延伸阅读与落地注意
权威参考
- RFC 5280 — X.509 证书与 CRL profile
- RFC 8446 — TLS 1.3
- OpenSSL x509 命令文档
落地时注意
- 证书过期是最常见故障之一;自动化续期(如 ACME)优于手工更换
- leaf 证书 应包含与访问域名一致的 SAN;仅靠 CN 已不足够
- 私有 PKI 要规划 根 CA 离线保管、中间 CA 轮换、吊销(CRL/OCSP),否则泄露中间 CA 私钥影响面大
- 公网服务配置 完整链 + OCSP Stapling,减少客户端缺链或吊销检查超时
- 将 CA 证书打进客户端只解决 「信任谁签发」;还需保证 hostname 校验、TLS 版本与 cipher 策略
10. 术语速查表
| 公钥 / 私钥 | 非对称密钥对;私钥保密,公钥可分发 |
| 数字证书 | 绑定「身份 + 公钥 + 有效期」并经 CA 签名的 X.509 文档 |
| X.509 | 数字证书的国际标准 结构与字段 |
| DER | X.509 等结构的 二进制 ASN.1 编码 |
| PEM | DER 的 Base64 文本包装,带 BEGIN/END 行 |
| CA | Certificate Authority,签发并背书证书的机构 |
| PKI | 公钥基础设施:CA 层级、签发、吊销、策略与信任分发 |
| Trust Store | 本地预信任的 根/中间 CA 集合 |
| 证书链 | 从叶子到根 CA 的逐级签名路径 |
| CSR | Certificate Signing Request,向 CA 申请证书的请求包 |
| SAN | Subject Alternative Name,证书适用的 DNS/IP 等名称列表 |
| mTLS | 双向 TLS,客户端与服务器互相出示证书 |
| CRL / OCSP | 证书吊销列表 / 在线吊销状态查询 |
| OCSP Stapling | 服务器在握手中附带 CA 签名的 OCSP 响应,客户端免直连 Responder |
| keyUsage / EKU | 约束公钥操作类型 / TLS serverAuth、clientAuth 等扩展用途 |
| AIA | Authority Information Access;可含中间 CA 下载地址(caIssuers) |
| 路径构建 | 从叶子到信任根的多种候选链中选择合法路径(含交叉签名) |
文档说明:概念层讲解,不涉及具体厂商实现;命令示例以 OpenSSL 为准,其他工具链语法可能略有差异。





