前言
"HTTPS是加密的"------这句话几乎每个开发者都说过。但如果追问:具体加密了什么?证书起什么作用?会话密钥又是怎么来的?很多人只能给出模糊的回答。
我把HTTPS的加密机制拆成三个部分来讲:证书验证身份、密钥交换建立安全通道、对称加密传输数据。理解这三步的分工,就理解了HTTPS加密的完整逻辑。
一、为什么需要HTTPS:HTTP的三个安全缺陷
HTTP协议以明文形式传输数据,这带来三个根本问题:
-
窃听风险:数据包经过的任何中间节点(路由器、代理、Wi-Fi热点)都能读取通信内容
-
篡改风险:中间人可以修改传输中的数据,接收方无法察觉
-
冒充风险:攻击者可以伪装成目标服务器,客户端无法验证对方的真实身份
HTTPS的本质是在HTTP和TCP之间插入一个安全层(TLS/SSL),解决上述三个问题。它的设计目标很明确:加密传输、校验完整性、验证身份。
二、核心矛盾:对称加密很快,但密钥怎么安全交换?
HTTPS加密面临一个根本性的两难:
对称加密(如AES)速度快,适合加密大量数据,但要求通信双方共享同一个密钥。问题在于:双方还没有建立安全通道,怎么安全地交换这个密钥?
非对称加密(如RSA)可以解决密钥分发问题------服务器公开公钥,客户端用公钥加密数据,服务器用私钥解密。但非对称加密计算开销极大,如果用它加密所有通信数据,性能无法接受。
TLS的解决方案是混合加密:
-
用非对称加密安全地交换一个临时的"会话密钥"
-
用这个会话密钥(对称加密)加密后续所有通信数据
这个设计兼顾了安全性和性能。非对称加密只用于握手阶段交换密钥,真正传输数据时用的是高速的对称加密。
三、TLS握手:从证书到会话密钥的完整过程
TLS握手是HTTPS建立安全连接的核心环节。以下以TLS 1.2的经典流程为例(TLS 1.3有优化,后面会讲)。
3.1 第一步:ClientHello------客户端发起请求
客户端(浏览器)向服务器发送ClientHello消息,包含:
-
支持的TLS版本(如TLS 1.2、TLS 1.3)
-
一个客户端生成的随机数(Client Random),后续用于生成会话密钥
-
支持的加密套件列表(如RSA、AES-GCM等)
-
SNI扩展(Server Name Indication):告知服务器客户端想访问的域名
关于SNI有一个关键细节:SNI信息是明文传输的。因为此时TLS连接尚未建立,双方还没有共享加密密钥。这意味着网络中间人(ISP、防火墙)可以看到你正在访问哪个网站,但看不到具体的通信内容。加密SNI(ESNI)是TLS 1.3的扩展,但部署率仍然有限。
3.2 第二步:ServerHello------服务器回应
服务器收到ClientHello后,返回ServerHello,包含:
-
确认使用的TLS版本
-
一个服务器生成的随机数(Server Random)
-
选定的加密套件
-
服务器证书(包含公钥)
服务器证书是HTTPS身份验证的核心。证书由受信任的证书颁发机构(CA)签发,包含服务器的公钥、域名、有效期以及CA的数字签名。
3.3 第三步:证书验证------客户端确认服务器身份
客户端收到证书后,执行验证:
-
检查证书是否由受信任的CA签发:浏览器内置了受信任的CA列表,证书的签发链必须能追溯到列表中的某个根CA
-
检查证书域名是否匹配:证书中声明的域名必须与客户端实际访问的域名一致
-
检查证书是否过期:过期的证书会被拒绝
-
检查证书是否被吊销:通过CRL或OCSP机制查询
如果验证失败,浏览器会显示安全警告。如果验证通过,客户端从证书中提取服务器的公钥。
关键点 :证书验证解决的是"我在和谁通信"的问题。公钥本身不保密(公钥就是公开的),证书的意义在于证明这个公钥确实属于目标服务器,而不是中间人伪造的。
3.4 第四步:密钥交换------生成会话密钥
客户端生成第三个随机数,称为Pre-Master Secret,然后用服务器的公钥加密这个随机数,发送给服务器。
服务器收到后,用自己的私钥解密,恢复出Pre-Master Secret。
此时,客户端和服务器各自拥有三个随机数:
-
Client Random(明文传输)
-
Server Random(明文传输)
-
Pre-Master Secret(加密传输)
双方用这三个随机数通过相同的算法计算出会话密钥(Session Key)。这个密钥是对称加密密钥,用于后续所有通信数据的加密。
为什么需要三个随机数? 单一随机数可能不够随机(受客户端或服务器的随机源质量影响)。三个随机数混合后,生成的会话密钥随机性更强,更难被猜测。
3.5 第五步:握手完成通知
客户端发送"编码改变通知",表示后续消息将使用协商的会话密钥加密。然后发送"客户端握手结束"消息,包含前面所有握手消息的哈希值。
服务器同样发送"编码改变通知"和"服务器握手结束"消息,进行验证。
握手完成后,双方开始使用会话密钥加密应用数据(HTTP请求和响应)。
四、TLS 1.3的改进:更少往返、更强安全
TLS 1.3对握手流程做了显著优化:
1. 握手消息加密:TLS 1.3中,ServerHello之后的所有握手消息都被加密,包括服务器证书。这解决了TLS 1.2中证书明文传输导致中间人可以观察到服务器身份的问题。
2. 前向保密(Forward Secrecy) :TLS 1.3移除了静态RSA密钥交换,强制使用(EC)DHE等支持前向保密的密钥交换算法。这意味着即使服务器的长期私钥未来被泄露,攻击者也无法解密之前记录的通信数据。
3. 更少的往返:TLS 1.3的完整握手只需要1-RTT(一次往返),相比TLS 1.2的2-RTT减少了一半。如果使用PSK(预共享密钥)会话恢复,可以实现0-RTT握手。
4. 移除不安全算法:TLS 1.3移除了RC4、3DES等弱加密算法,只保留AEAD(带关联数据的认证加密)算法。
五、HTTPS加密了什么,没加密什么
理解HTTPS的边界很重要:
加密的内容:
-
HTTP请求和响应体(页面内容、表单数据、API数据)
-
HTTP头部(Cookie、Authorization等)
-
握手完成后的所有应用层数据
不加密(或部分暴露)的内容:
-
目标域名(SNI) :TLS 1.2及之前的TLS 1.3中,SNI是明文的,中间人可以看到你在访问哪个网站
-
目标IP地址:数据包的目标IP在IP头部,不加密
-
端口号:443端口在TCP头部,不加密
-
通信的时序和流量大小:中间人可以观察到通信发生的时间和大致数据量
一个常见的误解:HTTPS不隐藏"你在和谁通信",它隐藏的是"你们说了什么"。SNI暴露了域名,IP暴露了服务器位置,但通信内容本身是加密的。
六、证书链与信任模型
浏览器不可能内置所有网站的证书。它内置的是根CA的证书 。服务器证书通常由中间CA签发,中间CA又由根CA签发,形成证书链。
验证时,浏览器沿着证书链向上追溯,直到找到一个受信任的根CA。只要链路上所有签名都有效,且根CA在浏览器的信任列表中,证书就被接受。
信任模型的核心:浏览器信任根CA,根CA为中间CA背书,中间CA为服务器证书背书。这是一套基于信任传递的层级模型。
风险:如果某个根CA或中间CA被攻破或行为不当,它可以为任意域名签发"合法"证书,从而实施中间人攻击。这也是为什么证书透明度(Certificate Transparency)机制被引入------所有CA签发的证书都会被公开记录,便于审计和发现异常签发。
七、总结
| 环节 | 使用技术 | 解决的问题 |
|---|---|---|
| 身份验证 | 数字证书 + CA签名 | 确认服务器真实身份 |
| 密钥交换 | 非对称加密(RSA/ECDHE) | 安全协商会话密钥 |
| 数据传输 | 对称加密(AES-GCM等) | 高效加密大量数据 |
HTTPS的加密机制可以概括为一句话:用非对称加密安全地交换一个对称密钥,然后用这个对称密钥加密所有通信数据。 证书负责证明公钥的归属,握手负责协商密钥,对称加密负责高效传输。
TLS 1.3进一步优化了握手流程,将握手消息加密、强制前向保密、减少往返次数,在保持兼容性的同时提升了安全性和性能。