一文弄懂ECDHE算法中的TLS握手流程

部分内容来源:小林coding


说一下ECDHE算法

DHE 算法由于计算性能不佳,因为需要做大量的乘法,为了提升 DHE 算法的性能,所以就出现了现在广泛用于密钥交换算法 —— ECDHE 算法

ECDHE 算法是在 DHE 算法的基础上利用了 ECC 椭圆曲线特性,可以用更少的计算量计算出公钥,以及最终的会话密钥。

小红和小明使用 ECDHE 密钥交换算法的过程:

  • 双方事先确定好使用哪种椭圆曲线,和曲线上的基点 G,这两个参数都是公开的;
  • 双方各自随机生成一个随机数作为私钥 d,并与基点 G 相乘得到公钥 Q(Q = dG),此时小红的公私钥为 Q1 和 d1,小明的公私钥为 Q2 和 d2;
  • 双方交换各自的公钥,最后小红计算点 (x1, y1) = d1Q2,小明计算点 (x2, y2) = d2Q1,由于椭圆曲线上是可以满足乘法交换和结合律,所以 d1Q2 = d1d2G = d2d1G = d2Q1 ,因此双方的 x 坐标是一样的,所以它是共享密钥,也就是会话密钥。

这个过程中,双方的私钥都是随机、临时生成的,都是不公开的,即使根据公开的信息(椭圆曲线、公钥、基点 G)也是很难计算出椭圆曲线上的离散对数(私钥)


ECDHE和RSA有什么区别? 

区别

RSA 和 ECDHE 握手过程的区别:

1.RSA 密钥协商算法「不支持」前向保密,ECDHE 密钥协商算法「支持」前向保密

2.使用了 RSA 密钥协商算法,TLS 完成四次握手后,才能进行应用数据传输 而对于 ECDHE 算法,客户端可以不用等服务端的最后一次 TLS 握手,就可以提前发出加密的 HTTP 数据,节省了一个消息的往返时间(这个是 RFC 文档规定的,具体原因文档没有说明,所以这点我也不太明白);

3.使用 ECDHE,在 TLS 第 2 次握手中,会出现服务器端发出的「Server Key Exchange」消息,而 RSA 握手过程没有该消息


总结

使用了 ECDHE,在 TLS 第四次握手前,客户端就已经发送了加密的 HTTP 数据

而对于 RSA 握手过程,必须要完成 TLS 四次握手,才能传输应用数据。

ECDHE 相比 RSA 握手过程省去了一个消息往返的时间,这个有点「抢跑」的意思,它被称为是「TLS False Start」,跟「TCP Fast Open」有点像,都是在还没连接完全建立前,就发送了应用数据,这样便提高了传输的效率


TLS第一次握手

客户端向服务端发送【Client Hello】

消息里面有

TLS版本号

支持密码套件

生成的随机数(Clinet Random)


TLS第二次握手

服务端向客户端发送【Server Hello】消息

消息内容有

确认TLS版本号

随机数(Server Random)

选择一个合适的密码套件

上面的操作都和RSA算法的TLS握手相同,但是选择的密码套件有点不同


密码套件

不过,这次选择的密码套件就和 RSA 不一样了,我们来分析一下这次的密码套件的意思。
「TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384」

  • 密钥协商算法使用 ECDHE;
  • 签名算法使用 RSA;
  • 握手后的通信使用 AES 对称算法,密钥长度 256 位,分组模式是 GCM;
  • 摘要算法使用 SHA384;
    接着,服务端为了证明自己的身份,发送「Certificate」消息,会把证书也发给客户端

因为服务端选择了 ECDHE 密钥协商算法,所以会在发送完证书后,发送「Server Key Exchange」消息

一文弄懂ECDHE算法中的TLS握手流程_第1张图片

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

  • 选择了名为 x25519 的椭圆曲线,选好了椭圆曲线相当于椭圆曲线基点 G 也定好了,这些都会公开给客户端;
  • 生成随机数作为服务端椭圆曲线的私钥,保留到本地;
  • 根据基点 G 和私钥计算出服务端的椭圆曲线公钥,这个会公开给客户端。

此公钥以明文形式传输。这是因为椭圆曲线密码学的特性保证了即使公钥被截获,攻击者也无法从公钥反推出私钥

为了保证这个椭圆曲线的公钥不被第三方篡改

服务端会用 RSA 签名算法给服务端的椭圆曲线公钥做个签名

客户端拿到这个椭圆曲线公钥后再用RSA算法签名做运算

随后,就是「Server Hello Done」消息,服务端跟客户端表明:“这些就是我提供的信息,打招呼完毕

至此,TLS 两次握手就已经完成了,目前客户端和服务端通过明文共享了这几个信息:

Client Random、Server Random 、使用的椭圆曲线、椭圆曲线基点 G、服务端椭圆曲线的公钥,这几个信息很重要,是后续生成会话密钥的材料


客户端验证证书

数字证书和 CA 机构

在说校验数字证书是否可信的过程前,我们先来看看数字证书是什么,一个数字证书通常包含了:

  • 公钥;
  • 持有者信息;
  • 证书认证机构(CA)的信息;
  • CA 对这份文件的数字签名及使用的算法;
  • 证书有效期;
  • 还有一些其他额外信息;


数字证书的目的是什么?

那数字证书的目的是用来认证公钥持有者的身份,以防止第三方进行冒充。说简单些,证书就是用来告诉客户端,该服务端是否是合法的,因为只有证书合法才代表服务端身份是可信的

我们用证书来认证公钥持有者的身份(服务端的身份),那证书又是怎么来的?又该怎么认证证书呢?

证书是怎么来的?

为了让服务端的公钥被大家信任,服务端的证书都是由 CA(Certificate Authority,证书认证机构)签名的,CA 就是网络世界里的公安局、公证中心,具有极高的可信度,所以由它来给各个公钥签名,信任的一方签发的证书,那必然证书也是被信任的。

之所以要签名,是因为签名的作用可以避免中间人在获取证书时对证书内容的篡改


数字证书签发和验证流程

一文弄懂ECDHE算法中的TLS握手流程_第2张图片

CA 签发证书的过程

如上图左边部分:

1.首先 CA 会把持有者的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;

2.然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书 做了签名;

3.最后将 Certificate Signature 添加在文件证书上,形成数字证书;

客户端校验服务端的数字证书的过程

如上图右边部分:

1.首先客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1

2.通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使用 CA 的公钥解密证书 Certificate Signature的内容,得到一个 Hash 值 H2

3.最后比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信


TLS第三次握手

客户端会生成一个随机数作为客户端椭圆曲线的私钥

然后再根据服务端前面给的信息,生成客户端的椭圆曲线公钥,然后用「Client Key Exchange」消息发给服务端

此公钥以明文形式传输。这是因为椭圆曲线密码学的特性保证了即使公钥被截获,攻击者也无法从公钥反推出私钥

一文弄懂ECDHE算法中的TLS握手流程_第3张图片

至此,双方都有对方的椭圆曲线公钥、自己的椭圆曲线私钥、椭圆曲线基点 G

于是,双方都就计算出点 (x, y) ,其中 x 坐标值双方都是一样的

前面说 ECDHE 算法时候,说 x 是会话密钥,但实际应用中,x 还不是最终的会话密钥

还记得 TLS 握手阶段,客户端和服务端都会生成了一个随机数传递给对方吗?
最终的会话密钥,就是用「客户端随机数 + 服务端随机数 + x(ECDHE 算法算出的共享密钥) 」三个材料生成的。

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

足够让黑客计算不出最终的会话密钥,安全性更高

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

接着,客户端会发「Encrypted Handshake Message」消息,对整个握手过程的完整性进行验证明

再用对称密钥加密一下数据

同时把之前发送的数据做一个摘要,然后把摘要加密发送给服务器让服务端做个验证,验证消息是否有被篡改


TLS第四次握手

服务端验证消息没被篡改,然后解密我们的数据,如果解密成功就是没问题

最后,服务端也会有一个同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息,如果双方都验证加密和解密没问题,那么握手正式完成。

于是,就可以正常收发加密的 HTTP 请求和响应了


简单说一下ECDHE握手流程 

TLS第一次握手

客户端:

向服务端发送【Client Hello】

消息里面有

TLS版本号

支持密码套件

生成的随机数(Clinet Random)


TLS第二次握手

服务端:

向客户端发送【Server Hello】消息

消息内容有

确认TLS版本号

随机数(Server Random)

选择一个合适的密码套件

发送「Certificate」消息,会把证书也发给客户端

因为服务端选择了 ECDHE 密钥协商算法,所以会在发送完证书后,发送「Server Key Exchange」消息

选择使用的椭圆曲线,选定椭圆曲线的G点

生成随机数作为椭圆曲线的私钥

根据G点+私钥服务端椭圆曲线的公钥

服务端会用 RSA 签名算法给服务端的椭圆曲线公钥做个签名

此公钥以明文形式传输。这是因为椭圆曲线密码学的特性保证了即使公钥被截获,攻击者也无法从公钥反推出私钥

ps:客户端拿到这个椭圆曲线公钥后再用RSA算法签名做运算(保证公钥不被篡改)

目前客户端和服务端通过明文共享了这几个信息:

Client Random、Server Random 、使用的椭圆曲线、椭圆曲线基点 G、服务端椭圆曲线的公钥,这几个信息很重要,是后续生成会话密钥的材料


客户端验证证书


TLS第三次握手

客户端:

会生成一个随机数作为客户端椭圆曲线的私钥

然后再根据服务端前面给的信息,生成客户端的椭圆曲线公钥,然后用「Client Key Exchange」消息发给服务端

此公钥以明文形式传输。这是因为椭圆曲线密码学的特性保证了即使公钥被截获,攻击者也无法从公钥反推出私钥

至此,双方都有对方的椭圆曲线公钥、自己的椭圆曲线私钥、椭圆曲线基点 G

于是,双方都就计算出点 (x, y) ,其中 x 坐标值双方都是一样的

前面说 ECDHE 算法时候,说 x 是会话密钥,但实际应用中,x 还不是最终的会话密钥

最终的会话密钥:用「客户端随机数 + 服务端随机数 + x(ECDHE 算法算出的共享密钥) 」三个材料生成的

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

接着,客户端会发「Encrypted Handshake Message」消息,对整个握手过程的完整性进行验证明

再用对称密钥加密一下数据

同时把之前发送的数据做一个摘要,然后把摘要加密发送给服务器让服务端做个验证,验证消息是否有被篡改

TLS第四次握手

服务端验证消息没被篡改,然后解密我们的数据,如果解密成功就是没问题

最后,服务端也会有一个同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息

如果双方都验证加密和解密没问题,那么握手正式完成

于是,就可以正常收发加密的 HTTP 请求和响应了


RSA和ECDHE的最终密钥有什么不同 

RSA的最终密钥:

三个随机数

Clinet Random,Server Random,Pre Master

用这三个生成最终会话密钥

ECDHE的最终密钥:

Clinet Random,Server Random,算出来的椭圆的X坐标

用这三个生成最终会话密钥

你可能感兴趣的:(java,网络协议,计算机网络,操作系统,spring,spring,boot)