本页目录

证书与 PKI

TLS 的安全基座——X.509 证书链、ACME 自动签发、OCSP/CRL 吊销检查、Certificate Transparency 公开审计。PKI 不是完美的(任何 CA 可以为任何域名签发证书),CT 和密钥固定是对这个信任模型的补丁。

概述

TLS 的信任基础是 X.509 证书和 PKI(Public Key Infrastructure)。浏览器/OS 预置了约 150 个 Root CA 证书——这些 CA 可以签发任何域名的证书,构成整个 HTTPS 信任体系的单点故障。Let's Encrypt(2016)通过 ACME 协议将证书签发自动化并完全免费,使 HTTPS 部署率从 40% 跃升到 90%+。Certificate Transparency(2013)强制所有证书记录在公开日志中,让恶意签发可被检测。OCSP Stapling 在保护隐私的同时实现吊销检查。

X.509 证书

Certificate:
  tbsCertificate (to-be-signed):
    Version: v3 (2)
    Serial Number: 随机 (CA 防重)
    Signature Algorithm: sha256WithRSAEncryption or ecdsa-with-SHA256
    Issuer: C=US, O=Let's Encrypt, CN=R3  ← 谁签的
    Validity:
      Not Before: 2024-01-01T00:00:00Z
      Not After:  2024-03-31T23:59:59Z (最大 90 days for LE)
    Subject: CN=grafana.liz6.com  ← 证书属于谁
    Subject Public Key Info:
      Algorithm: id-ecPublicKey (or rsaEncryption)
      Public Key: (256-bit EC point or 2048-bit RSA modulus)
    Extensions:
      SAN (Subject Alternative Name): grafana.liz6.com, *.liz6.com ← 关键!
      Basic Constraints: CA=FALSE ← 不是 CA (不能签发子证书)
      Key Usage: Digital Signature, Key Encipherment
      Extended Key Usage: TLS Web Server Authentication
      CRL Distribution Points: http://r3.i.lencr.org/
      Authority Information Access:
        OCSP: http://r3.o.lencr.org/
        CA Issuers: http://r3.i.lencr.org/
      Certificate Policies
      CT Precertificate SCTs (Signed Certificate Timestamps)
  Signature Algorithm
  Signature Value

SAN 的重要性

浏览器已完全忽略 CN (Common Name)。所有域名验证基于 SAN。如果证书没有包含访问的域名 → browser error: ERR_CERT_COMMON_NAME_INVALID:

SAN: DNS:grafana.liz6.com, DNS:*.liz6.com
→ 匹配 grafana.liz6.com ✓, chat.liz6.com ✓, grafana.liz6.com:8443 ✗ (SAN 不含端口)
→ 通配符: *.liz6.com 匹配单级子域 (chat.liz6.com) 但不匹配多级 (sub.chat.liz6.com)

Chain of Trust

Root CA (ISRG Root X1):
  Subject = Issuer = 自己 (自签)
  Basic Constraints: CA=TRUE
  → 预置在 OS/Browser trust store /etc/ssl/certs/

Intermediate CA (R3):
  Subject: R3, Issuer: ISRG Root X1 → 由 Root 签发
  Basic Constraints: CA=TRUE, pathLenConstraint=0 (不能再签发 CA)

Leaf (grafana.liz6.com):
  Subject: grafana.liz6.com, Issuer: R3 → 由 Intermediate 签发
  Basic Constraints: CA=FALSE

验证: 自下而上: leaf → R3 → Root → trust anchor (在 trust store 中)

ACME

客户端 (certbot/acme.sh) 通过 ACME v2 协议自动获取证书:

1. 创建 account: POST /acme/new-acct → account URL
2. 提交 order: POST /acme/new-order { identifiers: [grafana, *.liz6.com] }
   → order object + authorizations + challenges
3. 完成 challenges:
   HTTP-01: http://domain/.well-known/acme-challenge/<token>
            → CA 验证 GET 返回 key authorization = token + "." + thumbprint
   DNS-01:  放 TXT _acme-challenge.domain = key authorization
            → CA 验证 DNS (可签通配符!)
   TLS-ALPN-01: 在 ALPN 中返回 key authorization
4. 等待 validation → CA 验证 challenge
5. Finalize: POST CSR → CA 签发证书
6. Download: certificate chain (PEM, ~3-5KB)

OCSP 与 Revocation

OCSP (Online Certificate Status Protocol):
  Client: 问 CA "这个 serial number 的证书状态?"
  CA: "good" / "revoked" / "unknown"
  问题: CA 知道你在访问哪个网站 → 隐私 + 延迟 (额外 TLS 连接)

OCSP Stapling (RFC 6066, TLS Certificate Status Request extension):
  Server: 定期从 CA 获取 OCSP response (签名过的) → 缓存在本端
  TLS 握手: 在 CertificateStatus 消息中附带 OCSP response
  Client: 验证 OCSP response 的签名 → 不需要单独请求 OCSP
  → 隐私 + 延迟优化

CRL (Certificate Revocation List):
  定期发布的吊销证书列表 (整个 CA 范围内所有 revoked cert)
  缺点: 大 (可能 MB), 更新不及时 (通常 24h)
  OCSP 更实时 (but stapling needed for privacy)

Certificate Transparency

问题: 恶意的 CA (或被攻破的 CA) 签发 unauthorized 证书 → 中间人攻击

CT (RFC 6962):
  所有 certificate 提交到公开的 CT logs:
    → SCT (Signed Certificate Timestamp): log 给证书的"收据"
    → 浏览器验证: 证书至少含 2 个 SCT (来自不同 log operators)
  → Monitor: 任何人都可以监控 CT logs → 发现 unauthorized issuance

  你的证书: crt.sh/?domain=liz6.com → 查看所有 liz6.com 的证书历史

参考

  • RFC: 5280, 8555, 6960, 6962, 7633 (CT for code signing)
  • 工具⁠: openssl x509 -text -in cert.pem, crt.sh, certbot certificates

Keywords: X.509, SAN, chain of trust, ACME, Let's Encrypt, DNS-01, OCSP stapling, CRL, SCT, CT logs