HTTPS:加密通信与证书验证
上一篇我们看清了 HTTP 报文长什么样——但它有个致命问题:全程明文。请求行、头部、Cookie、请求体,路径上任何一个节点(路由器、Wi-Fi 热点、运营商、中间人)都能看见,甚至篡改。登录密码、支付信息这样裸奔,显然不行。HTTPS 就是来解决这个问题的。
很多人对 HTTPS 的理解停在"加了密"。但如果只是加密,会撞上一个根本性难题:你和服务器素未谋面,怎么在一条本就不可信的网络上,安全地协商出一把只有你俩知道的密钥? 更麻烦的是,你怎么确定屏幕那头真的是银行,而不是冒充银行的中间人? 加密、身份认证、密钥协商——这三件事缠在一起,才是 HTTPS 真正要解决的。
所以这一篇先机制后设计:先一步步走完 TLS 握手——双方到底交换了什么、证书怎么被验证、那把对称密钥是怎么在不泄露的前提下协商出来的——再回头解释为什么非得这么设计。
一、先厘清:HTTPS = HTTP over TLS
HTTPS 不是一个新协议,它就是 HTTP 跑在 TLS 之上。分层看:
- 上层还是你熟悉的 HTTP——方法、状态码、头部、实体,一字没变(上一篇讲的全都适用)。
- 中间多了一层 TLS(Transport Layer Security),负责把 HTTP 的字节加密后再交给 TCP。
- 下层仍是 TCP(HTTP/3 则是 QUIC 内置 TLS)。
所以 HTTPS 的工作流程是:先建 TCP 连接(三次握手)→ 再做 TLS 握手(建立安全通道)→ 之后的 HTTP 报文全部在这条加密通道里收发。HTTP 语义没变,只是不再裸奔。
HTTPS 要同时解决三件事,缺一不可:保密性(别人看不到内容)、完整性(内容没被篡改)、身份认证(确认对方真是它声称的那个域名)。只做加密而不做身份认证,等于把密码安全地交给了冒充者。
二、两种加密:为什么要混用对称与非对称
理解握手前,要先分清两类加密,这是整个机制的基石。
对称加密:加密和解密用同一把密钥。速度快、适合加密大量数据。问题是:通信双方怎么安全地拿到同一把密钥?在不可信网络上直接传密钥,等于公开它。
非对称加密:一对密钥——公钥公开给所有人,私钥自己严格保密。用公钥加密的数据,只有对应私钥能解;反之私钥"签名"的,公钥能验证。它巧妙解决了密钥分发问题,但运算慢,不适合加密大量数据。
HTTPS 的核心智慧:用非对称加密解决"如何安全协商出一把对称密钥",用对称加密负责"后续海量数据的高效加密"。 非对称负责建立信任和交换密钥(用一次),对称负责干重活(用一路)。各取所长。
三、证书:信任是怎么传递的
身份认证靠数字证书。证书的核心作用,是把"一个域名"和"一把公钥"可信地绑在一起——它本质是一份声明:“example.com 的公钥是这个,我以我的信誉担保。”
谁来担保?CA(证书颁发机构)。但你凭什么信这个 CA?答案是证书链:
- 你的浏览器/操作系统内置了一批受信任的根 CA证书(根证书)。
- 服务器的证书由某个中间 CA 签发,中间 CA 的证书又由根 CA 签发,形成一条链:
服务器证书 ← 中间 CA ← 根 CA。 - 验证时,浏览器逐级用上一级的公钥验证下一级证书的签名,一直追溯到自己信任的根 CA。链条完整、签名都对,就认可这张证书。
你不需要认识世界上每一个网站,只需要信任少数几个根 CA。信任通过证书链逐级传递下来。这套体系叫 PKI(公钥基础设施)。当然,前提是证书没过期、域名匹配、链条完整、没被吊销——任何一条不满足,浏览器就报警。
四、TLS 握手:一步步走完全过程
现在进入核心。我们以 TLS 1.2 的经典 RSA/ECDHE 流程为例,看双方到底交换了什么、密钥怎么协商出来。假设 TCP 三次握手已完成。
逐步拆解:
- ClientHello:客户端打招呼,告诉服务端"我支持哪些 TLS 版本、哪些密码套件",并附上一个随机数 R1。
- ServerHello:服务端从客户端的列表里选定一个 TLS 版本和密码套件,附上自己的随机数 R2。
- Certificate:服务端把自己的证书链发过来。
- ServerKeyExchange:在 ECDHE(椭圆曲线 DH)密钥交换中,服务端发出自己的密钥交换参数(并用私钥签名,证明这参数确实来自证书的持有者)。
- 客户端验证证书:检查证书链能否追溯到受信根 CA、域名是否匹配、是否过期。这一步若失败,握手中止、浏览器报警。
- ClientKeyExchange:客户端发出自己的密钥交换参数。
- 算出会话密钥:双方各自用
R1 + R2 + 协商出的预主密钥(pre-master secret)通过相同算法,各自独立计算出完全相同的会话密钥(对称密钥)。注意——这把对称密钥从未在网络上传输过,是双方分别算出来的。 - Finished:双方各发一个用会话密钥加密的 Finished 消息,互相验证"握手过程没被篡改、密钥也对得上"。
- 握手完成。此后所有 HTTP 报文都用这把会话密钥对称加密传输。
整个握手最精妙的一点:那把真正用来加密数据的对称密钥,自始至终没有在网络上传过。 用 ECDHE,双方只交换了"计算材料"(公开参数 + 两个随机数),各自在本地算出同一把密钥。即便全程被窃听,攻击者也凑不齐私有部分,算不出密钥。这就是它安全的根。
五、前向安全:为什么现代 TLS 偏爱 ECDHE
早期 TLS 用 RSA 做密钥交换:客户端生成预主密钥,用服务端公钥加密后发过去。这有个隐患——如果服务端私钥将来某天泄露,攻击者把之前录下的所有流量翻出来,就能用私钥解出当年的预主密钥,进而解密所有历史通信。
ECDHE(临时的椭圆曲线 Diffie-Hellman)解决了这个问题:每次握手用临时的密钥交换参数,会话结束就丢弃。即便服务端私钥日后泄露,也无法倒推出历史会话密钥——因为私钥只用于签名(证明身份),不参与密钥本身的生成。
这个特性叫前向安全(Forward Secrecy):一次密钥泄露,不会牵连过去的通信。这是现代 TLS 强烈推荐 ECDHE、逐步淘汰 RSA 密钥交换的核心原因。
TLS 1.3 更进一步,砍掉了不安全的旧套件、强制前向安全,并把握手压缩到 1 个 RTT(对比 1.2 的 2 个 RTT),还支持 0-RTT 恢复,既更安全又更快。
六、看懂机制后,再问:为什么这样设计
为什么不能只用对称加密? 因为对称加密要双方先有同一把密钥,而在不可信网络上安全分发这把密钥本身就是难题。非对称加密正是为破解"密钥分发"而生。
为什么不能全程用非对称加密? 因为它太慢——对每个 HTTP 报文都做非对称运算,性能无法接受。所以只用它来"协商出对称密钥"这一次,重活交给对称加密。
为什么加密之外还非要证书? 因为加密只保证"没人偷看",不保证"对方是谁"。没有身份认证,中间人可以把自己的公钥冒充成服务器的公钥,和你建立一条"加密但通向中间人"的通道——你加了密,却是对着骗子加密。证书 + CA 体系就是为了堵死这个中间人攻击。
七、和工程实践 / SRE 的联系
HTTPS 故障要先分清是握手阶段失败还是握手后 HTTP 处理失败——两者排查方向截然不同:
- 证书过期 / 域名不匹配 / 证书链不完整:最常见的握手失败。
openssl s_client -connect host:443能看到完整证书链和报错。证书链不完整(服务器漏配了中间 CA 证书)在某些客户端能过、某些过不了,特别隐蔽。 - SNI 配置错误:一个 IP 上托管多个 HTTPS 域名时,客户端在 ClientHello 里用 SNI 扩展指明要访问哪个域名,服务端据此返回对应证书。SNI 配错会返回错证书,导致域名不匹配。
- TLS 版本 / 密码套件不兼容:老客户端不支持新版本、或服务端禁用了旧套件,握手在 Hello 阶段就谈崩。
- 时间不同步:证书校验依赖系统时间。客户端时钟严重偏差,会把有效证书误判为"未生效"或"已过期"。
- 代理层回源证书校验:Nginx/CDN 回源到后端时也要校验后端证书,配置不当会出现"用户侧 HTTPS 正常,回源握手失败"。
- 性能优化:TLS 握手有成本,靠会话复用(Session Ticket / Session ID)、TLS 1.3、CDN 边缘终止 TLS、HTTP/2 多路复用来摊薄。现代硬件下 HTTPS 开销已经很小,安全收益远大于成本。
学习这一部分最容易踩的坑
1. 以为 HTTPS 就是"把内容加密"
加密只是三分之一。HTTPS 同时要解决保密、完整性、身份认证。少了身份认证,加密反而可能是"安全地把数据交给中间人"。
2. 以为对称密钥是服务端发给客户端的
现代 TLS(ECDHE)里,会话密钥是双方各自用交换的参数和随机数独立算出来的,从不在网络上传输。理解这点,才懂它为什么抗窃听。
3. 把证书的作用理解成"加密"
证书本身不负责加密,它负责绑定域名和公钥、证明身份。加密是握手协商出的会话密钥干的。证书是信任的凭据,不是加密工具。
4. 忽视前向安全
不理解前向安全,就不明白为什么要淘汰 RSA 密钥交换、力推 ECDHE。一旦私钥泄露,没有前向安全的历史流量会被全部解密。
总结
这一篇我们一步步走完了 TLS 握手,坚持先机制后设计:
- HTTPS = HTTP over TLS,HTTP 语义不变,TLS 负责在下层建立安全通道;
- 它同时解决保密、完整性、身份认证三件事,缺一不可;
- 混用两种加密:非对称解决密钥协商与身份,对称负责后续海量数据的高效加密;
- 证书把域名和公钥可信绑定,靠证书链逐级追溯到受信根 CA 完成验证;
- TLS 握手中,对称会话密钥由双方用随机数和交换参数各自独立算出,从不在网络传输;
- ECDHE 带来前向安全——私钥日后泄露也无法解密历史通信,是现代 TLS 的标配;
- 排障先分握手阶段还是握手后,证书、SNI、TLS 版本、时间是高频故障点。
把证书、握手、密钥协商、数据保护连成一条线,你就真正看懂了为什么今天的互联网几乎离不开 HTTPS。下一篇我们退回到访问的最起点——DNS:你输入的域名,是怎么找到这台服务器的。
参考资源:
- 《图解 HTTP》
- 《Web 性能权威指南》TLS 章节
- RFC 8446 - TLS 1.3
- Cloudflare - How HTTPS works