**交换是SSL/TLS握手中的重要内容:
**的协商和交换是TLS的一个关键,在握手过程中这是关键的也是耗时的一个步骤。**交换中有2个重点问题:
(1)**周期要尽可能短,最好是1次会话用1个**。
(2)**不能明文传输,一旦被窃听所有的努力都将白费。
看起来很矛盾,交换**是为了加密,而不传递**就无法实现加密传输,死循环了。为了解决这个问题我们就要使用非对称加密算法了,它的特点是一对**,公钥和私钥,公钥加密的数据,只用私钥能解密。非对称算法有RSA算法,DSA算法。除了非对称算法还可以使用DHE算法和基于DHE改进的ECDHE算法。我们用RSA算法来举例说明一下这个过程:
我们可以考虑使服务器拥有私钥和公钥,然后给每个客户端发送公钥,服务器把自己公钥以明文形式的发给客户端;然后客户端自己生成一个**,再用公钥加密这个**,要点是——这个加密的结果,只有私钥能解密,而私钥只在服务器端,也就是说,被非对称加密的**只能由服务器端解密;这样就完成了**交换,而且**不用以明文形式传输,其安全性是基于非对称加密算法的,非对称算法是基于某个数学难题的(私钥在服务器端,公钥一般在证书中)。如下:
(1):A对服务器B发起请求,B首先把公钥(包含在证书中)发给A(明文传输,证书是公开的)。
(2):A使用随机数算法,生成1个**key,并使用公钥进行加密,生成e(key),把e(key)发送到服务器B。
(3):B收到e(key),使用私钥进行解密从而得到key。
交换后,客户端和服务器都得到了**key(预主**)。
B发送公钥在TLS中是通过证书(certificate)报文发送的,certificate中的包含了公钥。key是通过Client key exchange报文发送的。
注意:在实际TLS中,key并没有直接被当成**,上面的描述省去了对key进行KDF等后续操作。
RSA面临的问题与其他交换算法:
RSA体系的最大问题是一旦私钥外泄,那么第三方就能从之前所有截获的被加密的**中解密出所有之前的key,使用key就可以**所有之前监听得到的密文。A与B之前所有的保密通信都归零了。这就是所谓的不支持前向安全(forward secrecy),私钥参与了**交换,安全性也随之取决于私钥的安全。其实之前提到的算法不止RSA算法,DHE, ECDHE都可以用于**交换。我们依次来谈谈剩下的几种:
(1)DHE算法交换秘钥流程:
临时Diffie-Hellman(ephemeral Diffie-Hellman,DHE)**交换是一种构造完备的算法。它的优点是支持前向保密,缺点是执行缓慢。
1)客户端A生成1个随机值x,使用x作为指数,即计算a = g^x mod p (g的x次方对p取模),p 是个大素数,g是生成数。客户端把 a 发送至服务器,x 作为自己私钥,且只有A自己知道。
2)服务器B和客户端A流程一样,生成一个随机值y,用y作为指数,计算
b = g^y mod p,将结果b发送至客户端,y自己保存。
3)客户端A收到 b 后计算key1 = b^x mod p
4)服务器B收到 a 后计算key2 = a^y mod p
根据数学定理 key1 = ((g^y mod p)^x )mod p = g^yx mod p
key2= ((g^x mod p)^y )mod p = g^xy mod p
g^xy = g^yx ,所以 key1 = key2 ,**交换成功,而且中间没有传输A B双方的私钥 x与y , 传输的只是 p ,g ,g^x mod p , g^y mod p ,在已知这四个数的情况下是很难得出 x与y的,这是依赖于离散对数这个难题。
以上过程与RSA**交换不同,DHE**交换时,服务器中的RSA私钥没有参与进来。也就是万一RSA私钥泄漏,也不会导致会话**被**出来,之前的通信还是安全的,具有前向保密性;即使是某一次的**外泄(也就是 x和y外泄),那么之前的加密数据也不会遭遇危险,因为每次都生成不同的x与y。
实际上,私钥的功能被削弱到用来身份认证。实际上DHE参数和b都是通过server key exchange发送给客户端,a通过client key exchange发送给服务器。server key exchange的结尾处需要用私钥对该报文本身进行签名,来证明自己拥有私钥,证明身份。
(2)ECDHE算法交换**流程:
理解了DHE**交换,那么理解ECDHE**交换原理并不难。如果数学方面的问题不深究的话,ECDHE的运算是把DHE中模幂运算替换成了点乘运算,速度更快,想**更难。 临时椭圆曲线Diffie-Hellman(ephemeral elliptic curve Diffie-Hellman,ECDHE)**交换建立在椭圆曲线加密的基础之上。椭圆曲线算法是相对较新的算法。
流程如下:
1)客户端A随机生成随机值a,计算F(x, y) = a * Q(x, y),将F(x, y)发送至服务器B。
2)服务器B随机生成随机值b,计算F(x,y) =b * Q(x, y)。将F(x, y)发送至客户端A。
3)客户端A计算key1(x, y) = a * (b * Q(x, y)) 。
4)服务器计算key2(x, y) = b *(a * Q(x, y)) 。
key1 = key2 = key,取key的x向量作为**(预主**)。
Q(x, y)为公认的某个椭圆曲线算法的基点。例如 secp256r1 与 secp384r1
在实际TLS**交换中,椭圆曲线secp256r1 和b通过server key exchange报文发送;a通过client key exchange报文发送。
推荐一个教程:https://ke.qq.com/course/382156
里面讲解TLS协议、加密算法;使用openssl 模拟整个CA签发私有证书;结合nginx,vsftp 部署证书,优化配置TLS等。