tangyuxian
文章79
标签37
分类5
算法-TLS/SSL握手过程

算法-TLS/SSL握手过程

TLS握手的过程,其实就是秘钥交换的过程

TLS握手的过程,其实就是秘钥交换的过程,这也是整个TLS加密技术里最复杂的一个环节,因为客户端与服务器端协商秘钥的过程对第三方都是透明的,那么秘钥协商的过程不仅要保证秘钥的保密性,还要考虑前向安全性

A. RSA算法交换秘钥

img

RSA交换秘钥流程:

1:服务器给客户端发送数字证书(服务器公钥、域名、CA签名)。

2:使用CA公钥对证书进行验签,验签成功即可证明服务器身份(公钥合法,没被篡改)。

3:生成对称加密的秘钥,使用公钥对其加密,发送给服务器。

4:服务器使用私钥解密,得到对称加密的秘钥。

5:客户端与服务器使用对称加密传输数据。

优点:通俗易懂,实现方便。

缺点:不具备前向安全性,因为使用RSA非对称加密参与了秘钥的协商过程,一旦将来私钥泄漏,那么之前所有的传输数据,都可以被解密。目前这种方式已经被淘汰了。

B. Diffie-Hellman算法交换秘钥

image-20210519153341372

image-20210519153845069

优点:RSA不参与协商秘钥,协商过程使用的参数N\G\X\Y都是一次性的,在客户端可服务器的内存中,即使销毁,整个加密过程具有前向安全性

缺点:计算需要很大的系统开销,效率低下。目前这种方式也已经不被使用了。

A. ECDHE椭圆曲线算法交换秘钥

ECDHE 算法是在 DHE 算法的基础上利用了 ECC 椭圆曲线特性,可以使用较少的开销计算出会话密钥。定理的推导过程:https://zhuanlan.zhihu.com/p/66794410 可以参考此文章。

我用 Wireshark 工具抓了用 ECDHE 密钥协商算法的 TSL 握手过程,可以看到是四次握手:

img

a. TLS 第一次握手

客户端首先会发一个「Client Hello」消息,消息里面有客户端使用的 TLS 版本号、支持的密码套件列表,以及生成的随机数(Client Random)。

img

b. TLS 第二次握手

服务端收到客户端的「Client Hello」,会返回「Server Hello」消息,消息面有服务器确认的 TLS 版本号,也给出了一个随机数(Server Random),然后从客户端的密码套件列表选择了一个合适的密码套件。

img

密码套件:Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

密钥协商算法使用 ECDHE

签名算法使用 RSA

握手后的通信使用 AES 对称算法,密钥长度 128位,分组模式是CBC

摘要算法使用 SHA

接着,服务端为了证明自己的身份,发送「Certificate」消息,会把证书也发给客户端。

img

继续发送「Server Key Exchange」消息

img

这个过程服务器做了三件事:

  1. 选择了名为 named_curve 的椭圆曲线,选好了椭圆曲线相当于椭圆曲线基点 G 也定好了,这些都会公开给客户端。

  2. 生成随机数作为服务端椭圆曲线的私钥,保留到本地。

  3. 根据基点 G 和私钥计算出服务端的椭圆曲线公钥,这个会公开给客户端。为了保证这个椭圆曲线的公钥不被第三方篡改,服务端会用 RSA 签名算法给服务端的椭圆曲线公钥做个签名。

继续发送[Server Hello Done」消息,服务端跟客户端表明:“这些就是我提供的信息,打招呼完毕”。

img

至此,TLS 两次握手就已经完成了,目前客户端和服务端通过明文共享了这几个信息:Client RandomServer Random使用的椭圆曲线椭圆曲线基点 G服务端椭圆曲线的公钥,这几个信息很重要,是后续生成会话密钥的材料。

c. TLS 第三次握手

客户端收到了服务端的证书后,自然要校验证书是否合法,如果证书合法,那么服务端到身份就是没问题的。校验证书到过程,会使用CA的公钥验证证书的签名,没问题了就可以继续往下进行。

如果证书验证不合法:

如果是Chrome浏览器,会给出警告提示,告诉你证书来源不合法,例如当年的12306,当然你也可以忽略警告,继续使用该证书也是可以的。

img

如果是SSL客户端程序,例如JAVA,会抛出证书验证不合法的错误。

img

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

解决办法:

1:去官方的CA认证中心对证书进行签名。

2:将我们自己创建的根证书提前导入浏览器。

3:配置客户端不检查证书来源。

客户端会生成一个随机数作为客户端椭圆曲线的私钥,然后再根据服务端前面给的信息,生成客户端的椭圆曲线公钥,然后用「Client Key Exchange」消息发给服务端。

img

至此,双方都有对方的椭圆曲线公钥、自己的椭圆曲线私钥、椭圆曲线基点 G。于是,双方都就计算出了共享秘钥。

还记得 TLS 握手阶段,客户端和服务端都会生成了一个随机数传递给对方吗?

最终的对称加密密钥,就是用「客户端随机数 + 服务端随机数 + (ECDHE 算法算出的共享密钥) 」三个材料生成的。

之所以这么麻烦,是因为 TLS 设计者不信任客户端或服务器「伪随机数」的可靠性,为了保证真正的完全随机,把三个不可靠的随机数混合起来,那么「随机」的程度就非常高了,安全性更高。

算好会话密钥后,客户端会发一个「****Change Cipher Spec****」消息,告诉服务端后续改用对称算法加密通信。

img

接着,客户端会发「Encrypted Handshake Message」消息,把之前发送的数据做一个摘要,再用对称密钥加密一下,让服务端做个验证,验证下本次生成的对称密钥是否可以正常使用。

img

d. TLS第四次握手

最后,服务端也会有一个同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息,如果双方都验证加密和解密没问题,那么握手正式完成。于是,就可以正常收发加密的 HTTP 请求和响应了。

img

img

本文作者:温故而知新666
文章来源:https://liuhuaqiang.blog.csdn.net/
本文链接:https://www.tangyuxian.com/2021/05/19/%E5%90%8E%E7%AB%AF/%E7%AE%97%E6%B3%95/%E7%AE%97%E6%B3%95-TLS-SSL%E6%8F%A1%E6%89%8B%E8%BF%87%E7%A8%8B/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可