为什么 HTTPS 是安全的,一张图告诉你
Category(分类): NET Protocol Status: 未知
本文保留原文“对称加密 → 非对称密码学 → 证书”的讲解顺序,并补充现代 TLS 1.3、ECDHE、X.509 证书和 HTTPS 的安全边界。
一、为什么要有 HTTPS
在 HTTPS 普及之前,很多 HTTP 请求和响应都以明文方式传输。如果有人在传输途中监听、抓包或控制网络设备,就可能读取登录信息、Cookie、页面内容和请求参数,也可能修改响应内容。
更安全的方法是对通信内容进行加密,并且验证通信对端的身份。HTTPS 的安全能力主要包括:
- 机密性:旁观者不能直接读取应用数据;
- 完整性:发现数据是否被传输中的攻击者修改;
- 服务器身份认证:验证访问域名对应的服务器是否持有可信证书和私钥;
- 可选的客户端认证:在双向 TLS 等场景中验证客户端证书。
现代 HTTPS 的准确表达是:
HTTPS = HTTP over TLS
SSL 是 TLS 的前身,SSL 2.0 和 SSL 3.0 已经废弃。现在的 HTTPS 主要使用 TLS 1.2 或 TLS 1.3,而不是简单的“HTTP 加 SSL”。
二、对称加密
对称加密指的是加密和解密使用同一个秘密密钥。
对称加密速度快,非常适合加密大量 HTTP 数据。现代 TLS 通常使用 AES-GCM、ChaCha20-Poly1305 等 AEAD 算法,它们不仅加密数据,还会验证密文和关联数据的完整性。

但是,在通信开始之前,客户端和服务端需要拥有同一个秘密密钥。问题是:如果网络本身不安全,如何把这把密钥安全地交给对方?
如果攻击者在密钥传输过程中获取了密钥,就可以读取后续密文;如果协议没有完整性保护,攻击者还可能修改通信内容。
因此,问题不是“对称加密不安全”,而是共享密钥如何安全协商。只要密钥安全分发,对称加密本身是非常可靠且高效的密码学工具。
三、非对称密码学
非对称密码学使用一对密钥:公钥和私钥。通常由服务端生成密钥对,并妥善保管私钥,公钥可以公开发布。
需要区分两类用途:
- 公钥加密、私钥解密:主要用于机密性;
- 私钥签名、公钥验证:主要用于身份认证和完整性。
把“私钥加密、公钥解密”作为普通加密流程,是早期教材对数字签名的简化类比,不应与真正的保密加密混用。

如果张大胖要把秘密消息发给 Bill,可以使用 Bill 的公钥加密,只有持有对应私钥的 Bill 才能解密。攻击者即使拿到了 Bill 的公钥,也不能因此解密这段密文。
但是,公钥本身不能证明它确实属于 Bill。如果攻击者把 Bill 的公钥替换成自己的公钥,张大胖可能会把消息加密给攻击者,这就引出了中间人攻击。
非对称密码学还存在性能问题:RSA、椭圆曲线签名和密钥协商的计算成本通常高于对称加密,不适合直接加密大量应用数据。因此 HTTPS 通常只在握手阶段使用非对称密码学,后续数据使用对称 AEAD 加密。
四、传输密钥的过程
1. 历史上的混合加密
早期 TLS 资料常用下面的比喻:
- 生成一个对称会话密钥 A;
- 使用服务端公钥加密密钥 A;
- 把加密后的密钥 A 发送给服务端;
- 服务端使用私钥解密获得密钥 A;
- 双方使用密钥 A 加密后续通信。
这种方式对应 TLS 1.2 中某些 RSA 密钥传输流程。它能够帮助理解“非对称密码学用于密钥传输、对称加密用于数据传输”的思想,但不是现代 TLS 1.3 的默认流程。
2. 现代 TLS 1.3 的 ECDHE
TLS 1.3 通常使用临时 ECDHE 密钥协商:
- 客户端和服务端分别生成临时密钥对;
- 双方交换临时公钥参数;
- 双方分别计算出相同的共享秘密;
- 使用 HKDF 从共享秘密和握手上下文派生不同用途的会话密钥;
- 使用会话密钥通过 AES-GCM 或 ChaCha20-Poly1305 保护 HTTP 数据。
现代 TLS 1.3 通常不会直接通过服务器证书公钥传输最终对称密钥。临时 ECDHE 还可以提供前向保密:即使服务端长期私钥日后泄露,也不能直接解密过去捕获的 TLS 1.3 会话数据。
五、中间人攻击
即使使用非对称密码学,也需要解决公钥归属问题。
如果 Bill 把自己的公钥直接发给张大胖,攻击者可以在传输过程中把公钥替换成自己的公钥。张大胖无法仅凭公钥内容判断它是不是 Bill 的公钥。攻击者随后可以分别与两边建立连接,读取并转发通信内容。
这就相当于张大胖想拨打 Bill 的电话,但中间人把 Bill 的号码替换成了自己的号码。张大胖以为自己正在和 Bill 通话,实际上连接的是中间人。
HTTPS 使用 X.509 数字证书和 CA 信任链,把服务器身份、域名和公钥绑定起来,从而降低这种攻击风险。
六、确认身份——数字证书
1. CA 和 X.509 证书
CA(Certificate Authority,证书颁发机构)是客户端信任的第三方机构。它会根据证书类型验证申请者对域名的控制权,或者验证组织身份,然后签发 X.509 证书。
证书通常包含:
- 服务器公钥;
- Subject Alternative Name(SAN),例如 DNS 名称或 IP 地址;
- 有效期;
- 序列号;
- 签发者;
- Basic Constraints、Key Usage、Extended Key Usage 等扩展;
- CA 对待签名证书内容生成的数字签名。
CA 的签名覆盖证书中的待签名内容。客户端使用签发者的公钥验证签名,而不是用 CA 公钥“解密证书”。
2. 证书验证过程
服务端发送证书链后,客户端通常会:
- 构建从服务器证书到受信任根 CA 的证书链;
- 验证每一级证书签名;
- 验证当前访问域名是否匹配 SAN 中的
dNSName; - 验证证书是否在有效期内;
- 验证证书用途和签名算法是否符合要求;
- 根据实现和策略检查 CRL、OCSP 或其他撤销状态;
- 在 TLS 握手中验证服务端确实持有证书对应的私钥。
域名验证现代应以 SAN 为准,不能只依赖证书 Subject 中的 Common Name(CN)。CA 证书通常由操作系统、浏览器或应用的信任库预置,但客户端并不会信任世界上所有 CA。
3. 域名验证和免费证书
CA 不只是通过邮箱验证域名。现在常见的域名控制权验证方式包括:
HTTP-01:在指定 HTTP 路径提供验证内容;DNS-01:发布_acme-challengeDNS TXT 记录;TLS-ALPN-01:通过 TLS ALPN 响应验证。
Let’s Encrypt 等 CA 可以免费签发 DV(Domain Validation)证书,但证书通常只有有限有效期,需要自动申请和续期。DV 证书主要证明申请者控制域名,并不等于 CA 证明了网站业务值得信任。
七、现代 HTTPS 的 TLS 1.3 握手
故事中的“公证处”可以帮助理解 CA,但真实 TLS 1.3 握手还包含密钥协商和握手认证:
客户端 服务端
| -------- ClientHello + key_share ------> |
| <------- ServerHello + key_share -------- |
| <------- EncryptedExtensions ------------ |
| <------- Certificate -------------------- |
| <------- CertificateVerify -------------- |
| <------- Finished ----------------------- |
| -------- Finished ---------------------> |
| <====== 加密的 HTTP Application Data ======> |
其中:
ClientHello和ServerHello协商 TLS 版本、密码套件和 ECDHE 参数;Certificate提供服务器证书链;CertificateVerify使用证书对应的私钥签署握手 transcript,证明服务端确实持有私钥;- 双方通过 ECDHE 共享秘密和 HKDF 派生握手密钥、应用数据密钥;
Finished用于确认双方看到的握手上下文一致;- 握手完成后,HTTP 数据通过 TLS 记录层使用 AEAD 加密和认证。
TLS 1.3 还支持会话恢复和 0-RTT 早期数据,但 0-RTT 可能被重放,不应直接用于支付、转账、修改密码等非幂等操作。
八、为什么 HTTPS 能够提供安全保护?
HTTPS 不是因为某一个“神奇的密钥”而安全,而是因为 TLS 把多种机制组合起来:
- 加密通信:对称 AEAD 算法保护应用数据机密性;
- 完整性保护:检测数据是否被篡改;
- 服务器身份认证:客户端验证证书、域名、证书链和握手签名;
- 密钥协商:ECDHE 让双方在不直接传输最终会话密钥的情况下得到共享秘密;
- 前向保密:现代临时密钥协商降低长期私钥泄露对历史会话的影响。
如果客户端验证不了证书、域名不匹配、信任根被替换、服务端私钥泄露,或者用户主动忽略浏览器警告,HTTPS 的身份保护就可能失效。
九、密钥的作用
最后回顾几类密钥的作用:
- 服务端长期私钥:证明服务器身份并参与握手签名,必须严格保护;
- 服务端证书公钥:公开提供,用于验证服务端签名等用途;
- CA 私钥:签发证书时生成 CA 签名,不能泄露;
- CA 根证书公钥:预置在客户端信任库中,用于验证证书链;
- ECDHE 临时私钥:参与计算本次连接的共享秘密;
- TLS 会话密钥:由握手秘密派生,用于加密本次连接的应用数据。

不同实现中密钥的数量和派生过程会更加复杂,TLS 1.3 会为客户端到服务端、服务端到客户端以及不同握手阶段派生不同的密钥,避免密钥重复使用。
十、HTTPS 的安全边界
HTTPS 主要保护客户端与 TLS 终止点之间的传输。如果 TLS 在 CDN、反向代理或负载均衡器处终止,那么该设备到源站之间是否继续使用 TLS,需要根据部署方案配置。
HTTPS 不能自动解决:
- 服务端被入侵;
- 客户端被恶意软件控制;
- XSS、CSRF、SQL 注入和权限漏洞;
- 用户主动访问的钓鱼域名;
- 应用把密码、Token 或 Cookie 不安全地记录到日志中。
实际项目还应配置安全 Cookie 属性、HSTS、混合内容检查、证书自动续期、私钥保护和合理的 TLS 版本策略。