我们知道,要加密数据,有对称加密算法和非对称加密算法。而非对称加密算法,由于对设备性能要求高,一般用来加密少量的数据。而在网络中我们传输的数据可是很大的,因此用对称加密算法来加密。不过对称加密算法的安全性,完全取决于对称加密密钥【后面简称密钥】。对密钥我们需要保证几点:
(1)通讯双方的密钥得一致,因为加解密都是用同一个密钥;
(2)不能被外界所知,也就是防止被窃取;
(3)不能被外界破坏,也就是防止被篡改。
那样怎么样才能得到这样一个密钥呢?有以下几种方法。
1. PSK方式得到密钥
1.1 PSK方式
最简单的方式,就是提前在客户端和服务器上配好,然后直接传输加密的数据,密钥不会在网络中传输,也就没有被窃取或篡改的风险。这就是我们所说的【PSK】方式。
不过有个问题是,如果一个客户端密钥被人拿到,那其他客户端与服务器通信的数据也会不安全。为了解决这个问题,我们可以在服务器给不同的客户端配置不同的密钥,这样就是一个客户端密钥被窃,也不会影响到其他客户端取。
1.2 【Identifier+PSK】:PSK方式的改进
不过当客户端发送数据时,除了发送加密的数据外,还得加上客户端的标识符(比如IP地址或者自定义的表示符),这样服务器收到数据后,根据标识符去找密钥然后解密数据。服务器要发送数据给客户端时,也得根据客户端标识符找密钥,然后加密发送。这其实就是是我们所说的【Identifier+PSK】方式。
不过这样做的问题是,当有N(N很大时)个客户端需要跟服务器通信时,是不是在服务器上要配置N个密钥,并且每个客户端都要配置一次密钥,除此之外如果要变更其中密钥也会不方便,因此这种方式会带来密钥维护与管理的问题。
【Identifier+PSK】方式应用场景针对少量的客户端,还是没有任何问题的。我们总结该方式的特点:
1)提前在双方配置好密钥,该密钥没有在网络中传输,不会在网络中被窃取或篡改
2)网络中传输的是标识符,被窃取后也无法解密数据,被篡改后服务器找不到客户端对应的标识符,解密失败重新开始
3)缺点也很明显,当客户端数量很多时,密钥管理和维护困难
2. 密钥交换算法来生成
PSK的方式,是提前在双方配置一样的密钥,换个思路,可不可以在每一次通信前期先传递密钥,这样密钥发送方和密钥接收方一致性没有问题,也不用提前在客户端或者服务器配置密钥,省去了密钥管理与维护的困难。
不过带来的问题就是密钥需要在网络中传输,增加了被窃取和篡改的风险。这个问题难不倒我们伟大的数学家,他们给我们搞了一堆算法用来保证密钥在网络中传输的安全性,而这些算法被称之为密钥交换/协商算法,常用的密钥交换算法有RSA、DH、DHE、ECDH、ECDHE。
2.1 RSA密钥交换的实现
如果我们直接在网络中传输密钥,那肯定是不可取的,这很容易被人窃取。如果我们把这个密钥,用公钥加密呢?那就只有公钥持有方才能解密,不怕窃取。RSA密钥交换正是使用了这种方式。
2.1.1 RSA密钥交换抓包分析
为了讲解RSA密钥交换算法,我人为指定服务器端的加密套件中的密钥交换算法为RSA,从Server Hello包的Cipher Suite可以看出。如下图所示:
我们可以看到Server Hello中的Cipher Suits为:TLS_RSA_WITH_AES_128_GCM_SHA256,其中RSA为密钥交换算法。另外如果密钥交换算法选定为RSA,后面在产生对称加密密钥的时候,其实只有一个数据包Client Key Exchange。
2.1.2 RSA密钥交换的安全性
Client Key Exchange 的形成比较复杂,不仅仅是对客户端产生的密钥加密而已,这里简单点,就把它理解成是客户端产生的密钥,然后用服务器公钥加密所形成,传给服务器后,服务器用私钥加密,就会得到跟客户端一样的密钥。外界拿到Client Key Exchange后,由于没有私钥,无法解密。
上面其实保证了密钥两点,通讯双方一致性和在网络中传输防止被窃取的风险。那如何防篡改:呢?如果被公钥加密后的密钥被篡改,会导致两端密钥不一致,进而解密失败,双方会知道被篡改从而重新开始。
2.1.3 总结下RSA密钥交换的特点
(1)需要证书持有方【SSL/TLS中是服务器】提前把证书给到证书接收方。
(2)密钥的产生其实只是证书接收方一个人完成的。
(3)密钥的安全性取决于私钥,如果私钥被窃取,密钥也就被解密,数据也就不安全。
2.1.4 RSA密钥交换存在的问题
第三方通过网络嗅探的方式拿到通信双方交互的所有报文,被加密也没关系,然后通过其他途径,比如黑到服务器,拿到私钥,进而解密密钥,从而解密双方的数据。 这就是常说的RSA密钥交换算法不支持前向保密【即PFS】。究其原因,还是私钥参与了密钥的协商。
我们wireshark解密SSL/TLS的包,就是基于这点,如果双方在Client Hello和Server Hello中协商出来的密钥交换算法是RSA时,完全可以把服务器的私钥导入到wireshark,解密密钥,从而解密数据。
2.2 DHE密钥交换的实现
DH 算法又称“Diffie–Hellman 算法”。这是两位数学牛人的名称,他们创立了这个算法。该算法可以做到:通讯双方在完全没有对方任何预先信息的条件下,通过不安全信道创建起一个密钥,该密钥双方是一样的。
该算法可以保证双方密钥的一致性,在网络传输中传输参数时不怕窃取,但是无法对抗篡改,因为它不支持认证。为了防止被篡改, 需要与其它签名算法(比如 RSA、DSA、ECDSA)配合,靠签名算法帮忙来进行身份认证。
2.2.1 先讲DHE算法的原理:
通讯双方(A、B)需要先约定好算法参数:素数 p 作为模数,素数 g 作为基数。这两个算法参数是可以对外公开滴。
(1)A产生随机数 Xa 作为私钥(不能公开),然后计算 Pa = q^Xa mod p作为自己的公钥(可以公开),发给B。
(2)B产生随机数 Xb 作为私钥(不能公开),然后计算 Pb = q^Xb mod p 作为自己的公钥(可以公开),发给A。
(3)A计算出Sa = Pb ^Xa mod p,B计算出Sb = Pa^Xb mod p。
(4) 算法保证了Sa = Sb = S,故密钥交换成功,S为密钥。
2.2.2 再讲DHE算法的安全性:
对于一个旁观者(偷窥者),虽然能看到 p,g,Pa,Pb,但是无法推算出 Xa 和 xb(就是说,旁观者无法推算出双方的私钥),自然也无法推算出 S(Sa或者Sb)。
DHE参数Pa通过client key exchange发送给服务器,Pb都是通过server key exchange发送给客户端。如果在网络中直接传输Pa、Pb的话,中间人虽然无法根据Pa、Pb算出密钥,但是却可以篡改Pa、Pb。
为了防止篡改,我们需要用RSA、DSA、ECDSA等前面算法来对Pa、Pb进行签名,然后分别放到client key exchange、server key exchange。为何签名后不能篡改,可以看RSA密钥交换算法防篡改的原理。
2.2.2 DHE算法与DH算法区别
DH算法相对于DHE算法,少了一步服务器B计算Pb的过程。Pb用证书中的公钥代替,而证书对应的私钥就是Xb。
因为SSL/TLS握手中认证的时候已经发送了server certificate,里面就已经包含了服务器的公钥Pb,因此不需要发送server key exchange报文。
由于DH算法,服务器的私钥也参与到密钥生成过程中,因此DH算法也不支持前向安全【PFS】。
2.3 ECDHE算法
2.3.1 ECDHE算法原理
只要理解DHE密钥交换原理,那么理解ECDHE密钥交换原理其实并不难(如果不想深究的话)。ECDHE的运算是把DHE中模幂运算替换成了点乘运算,用Q(x, y)【全世界公认的某个椭圆曲线算法的基点】代替了p、g。因此速度更快,可逆更难。
ECDHE算法流程如下:
(1)客户端随机生成随机值Ra,计算Pa(x, y) = Ra * Q(x, y),将Pa(x, y)发送至服务器。
(2)服务器随机生成随机值Rb,计算Pb(x, y) = Rb * Q(x, y),将Pb(x, y)发送至客户端。
(3)客户端计算Sa(x, y) = Ra * Pb(x, y);服务器计算Sb(x, y) = Rb *Pa(x, y)。
(4)算法保证了Sa = Sb = S,提取其中的S的x向量作为密钥(预主密钥)。
2.3.2 抓包分析ECDHE算法
从上图看到服务器选择的Cipher Suites中,除了密钥交换算法为ECDHE外,签名算法为RSA。也可以看出ECDHE算法中涉及到的几个报文交换如下:
(1)Server --> Client: Server Key Exchange,即Pb本身
(2)Client --> Server:Client Key Exchange ,即Pa经过签名后的值
3. 常用对称密钥生成算法比较
PFS | 密钥或密钥种子在网络中传输 | 是否防篡改 | SSL握手报文 | |
PSK | 不支持 | 否 | NA | NA |
Identifier+PSK | 不支持 | 否,网络传输的是Identifier | NA | NA |
RSA | 不支持 | 是 | 是 | Client Key Exchange |
DH | 不支持 | 是 | 否,需借助签名算法 | Client Key Exchange |
DHE | 支持 | 是 | 否,需借助签名算法 | Client Key Exchange, Server Key Exchange |
ECDH | 不支持 | 是 | 否,需借助签名算法 | Client Key Exchange |
ECDHE | 支持 | 是 | 否,需借助签名算法 | Client Key Exchange, Server Key Exchange |