真实面经题目 · 原创解析
HTTPS 的握手过程讲一讲?
HTTPS 的握手本质是 HTTP 通信前先通过 TLS 建立安全通道:客户端和服务端先协商 TLS 版本、密码套件和扩展参数,然后服务端用证书证明身份,双方通过密钥协商生成共享的对称会话密钥,再用 Finished 消息确认握手过程没有被篡改。握手完成后,HTTP 数据才通过对称加密、完整性校验和防重放机制进行传输。现代面试答案应以 ECDHE、TLS 1.2 和 TLS 1.3 为主,不能只讲早期 RSA 加密随机数的旧流程。
真实面经题目 · 原创解析
HTTPS 的握手本质是 HTTP 通信前先通过 TLS 建立安全通道:客户端和服务端先协商 TLS 版本、密码套件和扩展参数,然后服务端用证书证明身份,双方通过密钥协商生成共享的对称会话密钥,再用 Finished 消息确认握手过程没有被篡改。握手完成后,HTTP 数据才通过对称加密、完整性校验和防重放机制进行传输。现代面试答案应以 ECDHE、TLS 1.2 和 TLS 1.3 为主,不能只讲早期 RSA 加密随机数的旧流程。
HTTPS 可以理解为 HTTP over TLS。握手开始时,客户端发送 ClientHello,里面包含支持的 TLS 版本、随机数、密码套件列表、SNI、ALPN、支持的椭圆曲线组和签名算法等信息;在 TLS 1.3 中通常还会带上 key_share,用来提前提供客户端的临时 ECDHE 公钥。服务端收到后返回 ServerHello,选择协议版本、密码套件和密钥交换参数。接着服务端发送证书链,客户端会验证证书是否由可信 CA 签发、是否过期、域名是否匹配、用途是否正确以及是否被吊销。身份确认后,双方通过 ECDHE 计算出相同的共享秘密,再结合 ClientHello、ServerHello 里的随机数和整个握手摘要,派生出客户端和服务端各自方向的对称加密密钥。随后双方发送 Finished 消息,Finished 会基于握手 transcript 和密钥计算校验值,用来证明前面的协商没有被中间人篡改。Finished 校验通过后,TLS 安全通道建立完成,后续 HTTP 请求和响应使用 AES-GCM、ChaCha20-Poly1305 等对称加密算法传输。TLS 1.3 相比 TLS 1.2 减少了往返次数,默认使用具有前向安全的密钥交换,并把更多握手消息加密起来。会话复用方面,TLS 1.2 常见的是 session id 或 session ticket,TLS 1.3 使用 PSK ticket,可以减少握手开销,但 0-RTT 数据存在重放风险,只适合幂等请求。
TLS 握手不是单纯为了“交换一个密钥”,而是同时完成四件事:协商双方都支持的协议版本和密码套件,认证服务端身份,生成后续通信使用的对称加密密钥,确认整个握手过程没有被篡改。HTTPS 的安全性来自这些步骤的组合:证书解决“对方是谁”,密钥协商解决“怎么安全地产生共享密钥”,Finished 解决“前面的协商有没有被中间人改过”,应用数据加密解决“后续 HTTP 内容不被窃听和篡改”。
客户端首先发送 ClientHello。这个消息通常包含客户端支持的 TLS 版本、客户端随机数、密码套件列表、压缩方法、扩展字段等。现代 HTTPS 里非常重要的扩展包括 SNI、ALPN、supported_groups、signature_algorithms 和 key_share。SNI 用于告诉服务端客户端访问的域名,使同一个 IP 可以部署多张证书;ALPN 用于协商应用层协议,例如 HTTP/1.1 或 HTTP/2;supported_groups 和 key_share 与 ECDHE 密钥协商相关。在 TLS 1.3 中,客户端通常在 ClientHello 中直接带上临时密钥交换材料,从而减少握手往返。
服务端收到 ClientHello 后,会从客户端支持的能力中选择一组参数,并返回 ServerHello。它会确定 TLS 版本、密码套件、服务端随机数以及密钥交换相关参数。TLS 1.2 中,如果使用 ECDHE,服务端通常会发送 ServerKeyExchange,其中包含服务端临时 ECDHE 公钥,并用证书私钥对这些参数签名,证明这些密钥交换参数确实来自证书对应的服务端。TLS 1.3 中,ServerHello 选择客户端提供的 key_share 组并返回服务端的 key_share,后续 EncryptedExtensions、Certificate、CertificateVerify、Finished 等消息会更早进入加密保护。
服务端证书的作用是证明服务端身份,而不是直接加密全部业务数据。客户端会验证证书链是否能追溯到本地信任的根 CA,检查证书签名是否正确,检查证书是否在有效期内,检查访问域名是否匹配证书中的 SAN 字段,检查 key usage 和 extended key usage 是否符合服务端认证用途,并可能结合 OCSP、CRL 或 OCSP stapling 判断证书是否被吊销。如果验证失败,浏览器或客户端应终止连接或给出强警告。只有证书验证通过,后续密钥协商才有身份基础,否则中间人可以伪装成服务端。
现代 TLS 主要使用 ECDHE 完成密钥协商。客户端和服务端各自生成临时私钥和临时公钥,交换公钥后,双方独立计算出相同的共享秘密。这个共享秘密不会直接在网络上传输,中间人即使抓包也只能看到双方的临时公钥,无法得到最终共享秘密。TLS 1.2 会使用 PRF 结合 pre-master secret、客户端随机数和服务端随机数派生 master secret,再派生加密密钥、MAC 密钥或 AEAD 所需材料;TLS 1.3 使用 HKDF 和握手 transcript 派生 handshake traffic secret、application traffic secret 等更清晰的密钥层级。
握手得到的不是一个简单的“HTTPS 密码”,而是一组方向独立、用途明确的密钥材料。客户端到服务端、服务端到客户端通常使用不同的 traffic key 和 IV,这样可以隔离两个方向的数据保护。应用数据传输时主要使用对称加密算法,因为对称加密性能高,适合大量 HTTP 请求和响应。常见现代套件使用 AES-GCM 或 ChaCha20-Poly1305 这类 AEAD 算法,同时提供机密性和完整性保护。非对称算法主要用于身份认证、签名和密钥协商,不负责逐字节加密所有 HTTP 数据。
Finished 是握手中非常关键的收尾消息。它不是形式上的结束标记,而是用握手过程中派生出的密钥,对之前所有握手消息的 transcript 计算校验值。客户端和服务端收到对方的 Finished 后,会用自己计算出的结果进行比对。如果中间人修改过 ClientHello、ServerHello、证书、密钥交换参数或扩展协商,Finished 校验就会失败。TLS 1.2 中通常在 ChangeCipherSpec 后发送加密的 Finished;TLS 1.3 中 Finished 属于更精简的密钥调度流程,并且更多握手内容处于加密保护下。
握手完成后,HTTP 请求和响应才进入 TLS record 层进行加密传输。发送方会把应用数据分片、加密、附加认证信息,接收方解密并校验完整性。攻击者即使能监听网络,也只能看到连接目标的部分元信息、数据长度、时序等有限信息,无法直接读取请求路径、请求头、Cookie、请求体或响应内容。需要注意,DNS 查询、IP 地址、SNI 等信息在不同配置下可能仍有暴露风险,HTTPS 主要保护的是 TLS 连接内的应用层数据。
前向安全指的是:即使服务端证书私钥在未来泄露,攻击者也不能解密过去抓到的 TLS 流量。现代 TLS 通过临时 Diffie-Hellman,尤其是 ECDHE,实现这一点。每次握手都会生成临时密钥,握手结束后临时私钥应被丢弃,所以长期证书私钥不能还原过去的会话密钥。早期 RSA key exchange 模式下,客户端会生成 pre-master secret 并用服务端公钥加密发送,如果服务端私钥后来泄露,历史抓包可能被解密;这也是为什么现代答案不能把 RSA 加密随机数作为 HTTPS 握手的唯一流程。TLS 1.3 已经移除了传统 RSA key exchange。
完整握手需要额外往返和计算成本,所以 TLS 支持会话复用。TLS 1.2 中常见机制包括 session id 和 session ticket,客户端再次连接时可以携带之前的会话标识或票据,双方基于已有会话材料恢复密钥,减少证书验证和密钥协商成本。TLS 1.3 使用 PSK ticket,可以实现 1-RTT 恢复连接,甚至发送 0-RTT early data。0-RTT 虽然延迟更低,但存在重放风险,因此通常只适合 GET 等幂等操作,不应随意用于转账、下单、修改状态等请求。
TLS 1.3 减少了握手往返,简化了密码套件,移除了传统 RSA key exchange 和许多旧算法,默认使用具备前向安全的密钥交换。TLS 1.3 中客户端通常在 ClientHello 里带 key_share,服务端返回 ServerHello 后即可更快派生握手密钥,并把更多后续握手消息加密起来。
非对称密码学适合解决身份认证和安全协商问题,但计算成本高,不适合大量数据传输;对称加密性能高,适合加密 HTTP 请求和响应。HTTPS 的做法是握手阶段用证书、签名和 ECDHE 建立可信共享密钥,通信阶段用对称加密保护业务数据。
不一定。如果历史连接使用的是 ECDHE,并且临时私钥没有泄露,那么证书私钥泄露也不能还原过去的会话密钥,这就是前向安全。如果使用的是早期 RSA key exchange,攻击者又保存了历史抓包,那么服务端私钥泄露后可能解密历史流量。
关键在于证书验证和握手完整性校验。中间人即使拦截连接,也无法提供一个被客户端信任且域名匹配的有效证书;如果篡改握手参数,双方的 Finished 校验会失败。因此客户端必须正确验证证书,不能随意忽略证书错误。
SNI 让客户端在握手时告诉服务端自己要访问哪个域名,便于服务端在同一个 IP 上选择正确证书。ALPN 用于协商应用层协议,例如选择 HTTP/1.1、HTTP/2 或其他协议。它们都是 ClientHello 中常见且重要的扩展。
完整握手需要重新进行证书验证和密钥协商,成本更高。Session Ticket 让客户端携带服务端之前发放的恢复凭据,双方可以基于已有会话材料恢复或派生新的密钥,从而减少往返和计算开销。它是性能优化机制,不意味着明文通信。
0-RTT early data 可以在握手完全确认前发送应用数据,因此延迟很低,但这些数据可能被攻击者重放。服务端难以仅靠 TLS 层完全判断一次 0-RTT 请求是否已经被使用过,所以它只适合幂等请求,不适合支付、下单、修改资料等有副作用的操作。