深入理解 HTTPS:从 TLS 握手到证书链验证
Mei Lin | 2026-08-26T23:02:30 | Security
图文解析 TLS 1.3 握手的完整流程,讲解证书链验证机制,以及 HSTS、证书固定等安全加固措施。
# 深入理解 HTTPS:从 TLS 握手到证书链验证 ## TLS 1.3 握手流程 TLS 1.3 将握手从 2-RTT 优化到 1-RTT: ``` 客户端 服务端 |--- ClientHello ------------->| | (支持的密码套件、 | | Key Share) | | | || | | || ``` ## 密码套件 TLS 1.3 只保留了 5 个安全套件: ``` TLS_AES_128_GCM_SHA256 TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_AES_128_CCM_SHA256 TLS_AES_128_CCM_8_SHA256 ``` 移除了所有 RSA 密钥交换(改用 ECDHE),前向保密成为标配。 ## 证书链验证 ``` 根证书 (Root CA) |-- 颁发 --> 中间证书 (Intermediate CA) |-- 颁发 --> 服务器证书 (*.example.com) ``` 验证过程: ```python # 伪代码 def verify_chain(server_cert, intermediates, trust_store): current = server_cert # 1. 检查域名匹配 assert matches_domain(current, requested_host) # 2. 逐级验证签名 for issuer in intermediates: assert verify_signature(current, issuer.public_key) assert not is_expired(current) assert not is_revoked(current) # OCSP / CRL current = issuer # 3. 最终由根证书签名 root = find_in_trust_store(current.issuer, trust_store) assert verify_signature(current, root.public_key) return True ``` ## Nginx HTTPS 最佳配置 ```nginx server { listen 443 ssl http2; server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # 只启用 TLS 1.2 和 1.3 ssl_protocols TLSv1.2 TLSv1.3; # 安全的密码套件 ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; # HSTS(强制 HTTPS) add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; # OCSP Stapling(加速证书验证) ssl_stapling on; ssl_stapling_verify on; } ``` ## 常见问题排查 ```bash # 检查证书链是否完整 openssl s_client -connect example.com:443 -showcerts # 检查证书过期时间 echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates ```