接着上一篇 TLS Perfect Forward Secrecy 之 RSA 缺陷 继续来看看 DH/ECDHE 如何解决这个问题。
前面提到 RSA 做密钥协商过程中,最关键的缺陷是客户端用公钥加密了 PreMaster Key,服务器用私钥解密 PreMaster Key。理想中更好的方法是 公钥/私钥只用来对证书签名,不参与到密钥协商的过程中来,换句话说,希望通信的双方能独立计算
出对称加密的密钥。于是密码学家找到了尘封已久的,几乎与 RSA 同时出现的 DH 算法。
其实我一直有一个疑问:既然问题出在传送 PreMaster Key,那么客户端不发送 PreMaster Key 不就行了?握手的过程中已经有了 2 个随机数了,难道一定要 3 个随机数才能生成 master key 吗?
首先来看一下 DH 算法的数学基础。
+-------------------------------------------------------------------+
| Global Pulic Elements |
| |
| p prime number |
| a prime number, a < p |
+-------------------------------------------------------------------+
+-------------------------------------------------------------------+
| User A Key Generation |
| |
| Select private Xa Xa < p |
| Calculate public Ya Ya = a^Xa mod p |
+-------------------------------------------------------------------+
+-------------------------------------------------------------------+
| User B Key Generation |
| |
| Select private Xb Xb < p |
| Calculate public Yb Yb = a^Xb mod p |
+-------------------------------------------------------------------+
+-------------------------------------------------------------------+
| Calculation of Secret Key by User A |
| |
| Secret Key K K = Yb^Xa mod p |
+-------------------------------------------------------------------+
+-------------------------------------------------------------------+
| Calculation of Secret Key by User B |
| |
| Secret Key K K = Ya^Xb mod p |
+-------------------------------------------------------------------+
上面一共出现了 a, p, Xa, Ya, Xb, Yb, K 共 7 个数,其中:
- 公开的数:a, p, Ya, Yb
- 非公开数:Xa, Xb, K
通常情况下,a 一般为 2 或 5,而 p, Xa 和 Xb 的取值也非常大,其复杂度至少为 O(p^0.5)
。对于攻击者来说,已知 Ya,Xa 的求解非常困难,同理 Xb 的求解也很困难,所以攻击者难以求出 K,所以 DH 能够保证通信双方在透明的信道中安全的交换密钥。
看完了理论基础,我们用通俗的语言比较下 DH 和 RSA:
- DH 是用来协商创造密钥的,DH 不能直接用来对数据进行加密解密。
- RSA 可以用来加密解密,也可以用来传递密钥(尽管本文开头说了传递密钥有安全隐患)
- 注意:DH 是
协商创造
密钥,而 RSA 是传递
信息。
RSA算法的流程
- 客户端对服务器发起请求,服务器首先回复自己的公钥(公钥明文传输)
- 客户端使用随机数算法,生成一个密钥 S,使用收到的公钥进行 加密,生成C,把C发送到服务器
- 服务器收到 C,使用公钥对应的私钥进行解密,得到 S。
上述的 S 就是开头提到的 Premaster Key。
DH协商的流程
- 客户端计算一个随机值 Xa,使用 Xa 作为指数,即计算 Pa = q^Xa mod p,其中q和p是一对值。客户端把 Pa 发送至服务器,Xa 作为自己私钥。
- 服务器流程一样,生成一个随机值 Xb,使用 Xb 作为指数,计算 Pb = q^Xb mod p,将结果 Pb 发送至客户端,Xb自己保存。
- 客户端收到 P b后计算 Sa = Pb ^Xa mod p;服务器收到Pa后计算Sb = Pa^Xb mod p
- 算法保证了 Sa = Sb = S,密钥协商成功,S为 Premaster Key.
不难看出,上面的过程中服务器私钥没有参与进来,也就是说私钥即使泄漏,也不会导致会话加密密钥S被第三方解密,解决了本文开头提到的缺陷。
实际中,服务器私钥只用来身份认证。 更加详细的 DH 算法,请看参考资料1
ECDHE 算法
只要理解DHE密钥交换原理,那么理解ECDHE密钥交换并不难。ECDHE的运算是把DHE中模幂运算替换成了点乘运算,速度更快,可逆更难。
- 客户端随机生成随机值Ra,计算Pa(x, y) = Ra x Q(x, y),Q(x, y)为全世界公认的某个椭圆曲线算法的基点。将Pa(x, y)发送至服务器。
- 服务器随机生成随机值Rb,计算Pb(x,y) - Rb x Q(x, y)。将Pb(x, y)发送至客户端。
- 客户端计算Sa(x, y) = Ra x Pb(x, y);服务器计算Sb(x, y) = Rb x Pa(x, y)
- 算法保证了Sa = Sb = S,提取其中的S的x向量作为 Premaster Key。
下面重点比较一下这些缩写的区别,非常容易混淆….
ECDHE 与 ECDH
字面少了一个E,E代表了 临时
,即在握手流程中,作为服务器端,ECDH少了一步计算Pb的过程,Pb用证书中的公钥代替,而证书对应的私钥就是Xb。由此可见,使用ECDH密钥交换算法,服务器必须采用ECC证书;服务器不发送server key exchange报文,因为发送certificate报文时,证书本身就包含了Rb信息。
所以,有 E 的算法都支持 PFS,例如 DHE,ECDHE。
ECDHE 与 RSA
ECDHE(DHE)算法属于DH类密钥交换算法,私钥不参与密钥的协商,故即使私钥泄漏,客户端和服务器之间加密的报文都无法被解密,这叫 Perfect Forward Secrecy。由于ECDHE每条会话都重新计算一个密钥(Ra、Rb),故一条会话被解密后,其他会话仍旧安全。
ECDH 和 ECDSA
EC是椭圆曲线 elliptic curves 的意思,ECDSA 是签名算法,是DSA算法的一个变体。
ECDH 算法服务器端的私钥是固定的,即证书的私钥作为Rb,故 ECDH 不是前向安全,因为私钥泄漏相当于 Rb 泄漏,导致会话密钥可被第三方计算。
具体的算法流程,请参阅这一篇
参考资料
- https://blog.csdn.net/mrpre/article/details/52608867
- https://blog.csdn.net/mrpre/article/details/78025940
- https://blog.csdn.net/mrpre/article/details/72850644
- https://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy#diffie-hellman-with-discrete-logarithm
- https://www.zhihu.com/question/54320042
- https://www.acunetix.com/blog/articles/establishing-tls-ssl-connection-part-5/