HTTPS与TLS握手#
一句话答案#
HTTPS = HTTP + TLS 加密,握手:Client Hello→Server Hello+证书→密钥交换→对称加密通信。
核心要点
TLS 1.2 握手(4次往返,2-RTT):
客户端 服务端
│── ClientHello ──────────────────→│
│ (支持的TLS版本, 加密套件列表, │
│ 客户端随机数 C_Random) │
│ │
│← ServerHello ──────────────────── │
│ (选定的TLS版本, 加密套件, │
│ 服务端随机数 S_Random) │
│ │
│← Certificate ──────────────────── │
│ (服务端的数字证书,含公钥) │
│ │
│← ServerHelloDone ──────────────── │
│ │
│── ClientKeyExchange ────────────→│
│ (用服务端公钥加密的 pre-master │
│ secret,或 ECDHE 的客户端公钥) │
│ │
双方各自根据:C_Random + S_Random + pre-master secret
生成相同的 Master Secret → 派生出对称加密密钥
│ │
│── ChangeCipherSpec ─────────────→│ 切换到加密模式
│── Finished(加密)──────────────→│
│← ChangeCipherSpec ─────────────── │
│← Finished(加密)──────────────── │
│ │
─────── 握手完成,开始加密通信 ──────plaintextTLS 1.3 优化(1-RTT,甚至 0-RTT):
- 精简了握手,去掉了 ServerHelloDone、ChangeCipherSpec 等消息
- 只支持前向安全的密钥交换算法(ECDHE),不再支持 RSA 静态密钥交换
- 0-RTT 恢复会话(Session Resumption)
客户端如何验证 CA 证书的有效性:
证书链验证:
服务端证书(由中间 CA 签名)
→ 中间 CA 证书(由根 CA 签名)
→ 根 CA 证书(由操作系统/浏览器内置信任)
验证流程:
1. 用中间 CA 的公钥验证服务端证书的签名 → 合法(确认证书是中间 CA 颁发的)
2. 用根 CA 的公钥验证中间 CA 证书的签名 → 合法
3. 根 CA 证书在操作系统受信任根证书列表中 → 整个链可信plaintext其他验证项:
- 域名匹配:证书中的 CN(Common Name)或 SAN 是否与访问的域名一致
- 有效期:证书是否在有效期内(notBefore ~ notAfter)
- 吊销状态:
- CRL(Certificate Revocation List):下载吊销列表检查
- OCSP(Online Certificate Status Protocol):在线实时查询证书状态
三个深挖点:签名、Finished、前向安全#
1. 数字签名的本质 = 哈希 + 私钥加密
证书”由 CA 签名”到底签了什么、怎么验?
CA 签发时:
对证书内容(域名、公钥、有效期…)做哈希 → 得到摘要 digest
用 CA 的【私钥】加密 digest → 这就是"数字签名",附在证书里
客户端验证时:
① 同样对证书内容做一遍哈希 → 得到 digest1
② 用 CA 的【公钥】解密签名 → 得到 digest2
③ 比对 digest1 == digest2 ?
相等 → 证书内容没被篡改,且确实是这个 CA 用私钥签的
不等 → 证书被改过 / 不是该 CA 签的,验证失败plaintext- 为什么能防伪造:只有 CA 持有私钥,别人无法伪造出能被 CA 公钥正确解开的签名。
- 为什么能防篡改:改了证书任何一个字节(比如把域名换成自己的),哈希就变了,digest1 ≠ digest2,立刻露馅。
- 这同时验证了两件事:证书未被篡改 + 该公钥确实属于这个域名(因为域名和公钥都在被签名的内容里)。
注意方向:日常加密是”公钥加密、私钥解密”;签名正好相反——私钥加密(签)、公钥解密(验),因为目的不是保密而是证明”这是私钥持有者干的”。
2. Finished 报文:握手的防篡改/防降级校验
握手前半段(ClientHello、加密套件协商等)大多是明文传输的,中间人可以悄悄篡改,比如把”支持 TLS 1.3”改成”只支持弱加密套件”来发起降级攻击。Finished 就是用来兜底的:
- Finished 报文里携带一个对前面所有握手消息计算出的 MAC(基于已协商出的密钥)。
- 双方各自把自己看到的握手消息序列算一遍 MAC,互相核对。
- 如果中间人改过任何一条握手消息,两边算出的 MAC 对不上,握手直接失败中断。
- 因为 MAC 依赖刚协商出的会话密钥,中间人没有密钥就伪造不出正确的 Finished,于是篡改和降级都会被发现。
3. ECDHE 与前向安全(Forward Secrecy)
这是 TLS 1.3 弃用 RSA 静态密钥交换、只保留 ECDHE 的根本原因。
| 密钥交换方式 | 做法 | 风险 |
|---|---|---|
| RSA 静态 | 客户端用服务器证书里的长期公钥加密 pre-master secret 发过去 | 一旦服务器长期私钥泄露,攻击者可解开历史上抓包存下的所有流量 |
| ECDHE 临时 | 每次握手双方临时生成一对椭圆曲线密钥做 DH 交换,算出本次会话密钥,握手后临时私钥即丢弃 | 长期私钥只用于”签名证明身份”,不参与加密会话密钥 |
前向安全:每次会话用的是一次性临时密钥,即使服务器长期私钥日后泄露,也无法倒推出历史会话密钥、解密过去的流量。RSA 静态交换不具备这个性质——长期私钥就是历史流量的总钥匙,所以 TLS 1.3 直接废弃了它。
面试回答(2分钟版)
HTTPS本质是HTTP加上TLS加密层。以TLS 1.2为例,握手过程是这样的:客户端先发ClientHello,携带支持的TLS版本、加密套件列表和一个客户端随机数;服务端回复ServerHello选定加密套件,附带服务端随机数和数字证书。客户端收到证书后进行验证,包括证书链校验、域名匹配、有效期和吊销状态检查。验证通过后客户端生成pre-master secret,用服务端公钥加密发送过去。双方各自根据客户端随机数、服务端随机数和pre-master secret计算出相同的Master Secret,派生出对称加密密钥,之后所有数据传输都用对称加密。这里的核心设计是非对称加密只用于密钥交换阶段,数据传输用对称加密保证性能。TLS 1.3做了重大优化,握手从2个RTT降到1个RTT,只保留前向安全的ECDHE算法,还支持0-RTT会话恢复。需要注意的是HTTPS并非绝对安全,如果客户端不校验证书仍然可能遭受中间人攻击。
追问与易错
追问方向:
- “对称加密和非对称加密各用在哪?”→ 非对称加密(RSA/ECDHE)用于 TLS 握手阶段交换密钥,对称加密(AES)用于后续数据传输,兼顾安全和性能
- “数字证书怎么验证真伪?”→ 用 CA 公钥验证证书签名 + 证书链逐级校验到根 CA + 检查域名匹配、有效期和吊销状态(CRL/OCSP)
- “HTTPS 比 HTTP 慢多少?怎么优化?”→ TLS 1.2 握手增加 2-RTT,优化方案:升级 TLS 1.3(1-RTT)、Session 复用(0-RTT)、OCSP Stapling 减少证书验证延迟
- “数字签名到底是怎么做的?”→ 哈希 + 私钥加密:CA 对证书内容哈希后用 CA 私钥加密成签名;客户端用 CA 公钥解密签名得到摘要,再自己对证书算一遍哈希比对,相等说明证书未被篡改且确属该域名。方向和加密相反(私钥签、公钥验)
- “Finished 报文有什么用?”→ 对前面所有握手消息做 MAC 校验,两端互相核对;中间人篡改任何握手消息或发起降级攻击都会导致 MAC 对不上、握手中断,且中间人无会话密钥伪造不出正确 Finished
- “什么是前向安全?为什么 TLS 1.3 弃用 RSA 密钥交换?”→ ECDHE 每次握手用一次性临时密钥对,长期私钥只用于签名不参与加密会话密钥;即使长期私钥日后泄露也无法解密历史流量。RSA 静态交换中长期私钥是历史流量的总钥匙、不具备前向安全,故被废弃
易错点:
- ❌ “HTTPS 全程非对称加密”——只有密钥交换用非对称,数据传输用对称(性能考虑)
- ❌ “有了 HTTPS 就绝对安全”——中间人攻击仍可能(如客户端不验证证书)
- ❌ “签名就是把证书用私钥加密”——签的是证书内容的哈希摘要,不是整张证书;且签名方向是私钥签、公钥验,与加密保密相反