可以看到,这种方式合并了密钥交换和服务端认证两个步骤,如果服务端能解密 Premaster Secret,也就意味着服务端拥有正确的私钥。中间人没有私钥,无法得到 Premaster Secret,也就无法解密后续流量。
对于 Wireshark 来说,配置某个网站的私钥后,能解密这个网站「使用 RSA 进行密钥交换」的加密流量就很容易理解了。
显然,RSA 密钥交换有一个很大的问题:没有前向安全性(Forward Secrecy)。这意味着攻击者可以把监听到的加密流量先存起来,后续一旦拿到了私钥,之前所有流量都可以成功解密。
实际上,目前大部分 HTTPS 流量用的都是 ECDHE 密钥交换。ECDHE 是使用椭圆曲线(ECC)的 DH(Diffie-Hellman)算法。下图是 DH 密钥交换过程:
图片来源ssl handshake diffie hellman
上图中的 Server DH Parameter 是用证书私钥签名的,客户端使用证书公钥就可以验证服务端合法性。相比 RSA 密钥交换,DH 由传递 Premaster Scret 变成了传递 DH 算法所需的 Parameter,然后双方各自算出 Premaster Secret。
对于这种情况,由于 Premaster Secret 无需交换,中间人就算有私钥也无法获得 Premaster Secret 和 Master Secret。也就是说 Wireshark 无法通过配置 RSA Private Key 的方式解密「使用 ECDHE 进行密钥交换」的加密流量。当然,使用 ECDHE 后,虽然中间人拿到私钥也无法解密之前的流量,但他可以实施 MITM 攻击来解密之后的流量,所以私钥还是要保管好。
相比 RSA 既可以用于密钥交换,又可以用于数字签名;ECC 这边就分得比较清楚了:ECDHE 用于密钥交换,ECDSA 用于数字签名。也就是目前密钥交换 + 签名有三种主流选择:
RSA 密钥交换、RSA 数字签名;
ECDHE 密钥交换、RSA 数字签名;
ECDHE 密钥交换、ECDSA 数字签名;
以下是使用这三种密钥交换方式的网站在 Chrome 中的截图:
key exchange
HTTP/2 中只能使用 TLSv1.2+,还禁用了几百种 CipherSuite(详见:TLS 1.2 Cipher Suite Black List)。实际上,HTTP/2 允许使用的 CipherSuite 必须采用具有前向安全性的密钥交换算法,不允许使用 RSA 密钥交换。这也是为什么 RSA Private Key 无法解密 HTTP/2 加密流量。
SSLKEYLOGFILEFirefox 和 Chrome 都会在系统环境变量存在 SSLKEYLOGFILE 文件路径时,将每个 HTTPS 连接产生的 Premaster Secret 或 Master Secret 存下来。有了这个文件,Wireshark 就可以轻松解密 HTTPS 流量,即使是使用了 ECDHE 这种具有前向安全性的密钥交换,如下图:
decrypt http2 over tls
SSLKEYLOGFILE 文件记录的是 HTTPS 数据传输中最重要的加密信息,如果不是出于调试目的,一般也没人会主动配置这个环境变量,所以这个方案基本不会对 HTTPS 安全性产生影响。
总结Fiddler 这类工具通过往系统导入根证书来实现 HTTPS 流量解密,充当中间人角色。要防范真正的 HTTPS 中间人攻击,网站方需要保管好自己的证书私钥和域名认证信息,为了防范不良 CA 非法向第三方签发自己的网站证书,还要尽可能启用 Certificate Transparency、HTTP Public Key Pinning 等策略;用户方不要随便信任来历不明的证书,更不要随意导入证书到根证书列表,还要养成经常检查常用网站证书链的习惯。
RSA 密钥交换没有前向安全性,这意味着一旦私钥泄漏,之前所有加密流量都可以解开。为此,网站方需要启用使用 ECDHE 作为密钥交换的 CipherSuite,或者直接使用 ECC 证书;用户方需要弃用不支持 ECDHE 的古董操作系统及浏览器。
对于浏览器而言,HTTPS 毫无秘密,通过浏览器生成的 SSLKEYLOGFILE 文件,Wireshark 可以轻松解密 HTTPS 流量。另外,如果浏览器被安装恶意扩展,即使访问安全的 HTTPS 网站,提交的数据一样可以被截获。这种客户端被攻击者控制引发的安全问题,无法通过 HTTPS 来解决。