面试官你不要说我不懂TLS握手了

2021-11-25 14:11:24 浏览数 (1)

摘要

  1. 基于RSA密钥协商算法的TLS1.2握手分析
  2. 数字证书
  3. DHE和ECDHE算法
  4. 基于ECDHE密钥协商算法的TLS1.2握手分析

TLS握手时采用的加密方式

非对称加密和对称加密。

非对称加密主要用来保护对称加密密钥交换的安全性,一旦客户端和服务端交换密钥完成,即可使用密钥采用对称加密的方式进行通信。

基于RSA密钥协商算法的TLS1.2握手分析

TLS握手的总过程

TLS1.2握手的过程由于本人本地密码套件不支持,相关图片来源于网络。

  • 第一次握手客户端的发起的ClientHello请求
  • 第二次握手ServerHello,发送相关信息和证书给客户端
  • 第三次握手客户端发送请求给服务端
  • 第四次握手服务端响应客户端的第三次握手

客户端的ClientHello

  • Version:客户端使用的TLS的版本号,这里是1.2
  • Random:随机数,这个随机数会被服务端保留,后续用来生成对称密钥
  • CipherSuites:支持的加密方式列表

服务端的ServerHello

  • version:确认支持TLS的版本,这里为1.2
  • Random:服务器端的随机数,此随机数后续用来生成对称密钥
  • Cipher Suite:确认使用的加密算法

Cipher Suite的格式

Cipher Suite虽然很长,但是它是一个固定格式,基本的格式为:

密钥交换算法 签名算法 WITH 对称加密算法 摘要算法。

比如上图中的我们的使用的算法分别为:

  • 密钥交换算法:RSA
  • 证书的签名验证算法:RSA(这里由于WITH前面只有一个RSA,所以签名算法也是RSA)
  • 握手后的通信对称加密算法:AES对称算法,密钥长度为128位,分组模式是GCM
  • 摘要算法:SHA256

服务端如何证明自己的身份

服务端为了证明自己的身份会发送Server Certificate给客户端,这个消息里面包含数字证书。具体信息如下:

除了发送了证书,服务端还发送了Server Hello Done消息,目的是告诉客户端你要的东西我都给你了。具体内容如下:

TLS第三次握手

客户端在验证证书无误后,会发起第三次握手请求,首先会发送Client Key Exchange消息,内容如下:

客户段会生成pre-master随机数,并使用服务端RSA公钥进行加密发送给服务器,Encrypted PreMaster就是经过加密后的随机数,服务器收到后可以使用私钥解密。

至此,客户段使用三个随机数可以生成会话密钥了,于是生成会话密钥以后会发送一个Change Cipher Spec消息告诉服务端开始使用加密的方式传输。

最后客户端会发送一个Encrypted HandShake Message,这个就是把之前的数据做个摘要,然后再用会话密钥加密发送给服务器,供服务器验证。

TLS第四次握手

第4次握手其实就是服务器发送个Change Cipher Spec消息(由于服务器收到了第三个随机数,因此也可以生成会话密钥,后续可以加密传输了)和个Encrypted HandShake Message消息,握手完成。

可以看出,Change Cipher Spec之前的消息都是明文传输,之后都是通过对称密钥加密传输。

数字证书

数字证书包含的内容

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

数字证书如何签发

  1. CA会对持有者的公钥、用途、有效时间等信息打成一个包,然后对着信息进行计算,获得一个hash值
  2. CA会使用自己的私钥将该hash值加密,生成签名
  3. 最后将签名添加在文件证书上,形成数字证书

客户端如何校验服务端的数字证书

  1. 客户端使用相同的算法计算服务器数字证书的hash值(假设这里的代号为H1)
  2. 由于浏览器和操作系统集成了CA的公钥信息,浏览器在收到证书后通过CA进行解密签名内容获得一个hash值(H2)
  3. 比较H1和H2的值,相同证书可信,否则不可信

证书链是啥

我们向CA申请的证书一般都不是由根证书签发,而是由中间证书签发,比如上述思否(segmentfault.com)的证书,证书有三级。

那么具体的验证过程如下:

  • 客户端在收到思否(segmentfault.com)的证书以后,发现证书的签发者不是根证书,因此无法根据本地已有根证书中的公钥去验证segmentfault.com是否可信。因此客户端需要找到该证书的签发者DigiCert TLS RSA SHA256 2020 CA1,然后向该CA请求中间证书
  • 请求到DigiCert TLS RSA SHA256 2020 CA1证书以后,发现它还不是根证书,但是它的上级签发机构DigiCert Global Root CA已经没有上级,说明DigiCert Global Root CA是根证书。此时应用软件会检查DigiCert Global Root CA证书是否已经预载到系统中,如果有可以根据证书中的公钥验证DigiCert TLS RSA SHA256 2020 CA1证书,验证通过则认为中间证书可信。
  • DigiCert TLS RSA SHA256 2020 CA1证书被信任以后,可以使用它包含的公钥去验证思否(segmentfault.com)的证书,验证通过则信任该证书。

从上图中可以看出思否证书的签发根证书DigiCert Global Root CA已经在我的MacOS操作系统中预置。

DHE和ECDHE算法

RSA密钥协商算法的缺陷

由于我们的客户端传递随机数都是使用公钥加密,服务端收到后使用私钥解密。所以一旦我们服务器的私钥遭到泄漏,我们就可以对过往截获服务器客户端的TLS报文进行解密(无法向前保密)。

今日截获数据,明日(或未来)解密数据。

RSA有缺陷如何解决

RSA密钥协商算法既然无法向前保密,后面使用了新的协商算法:

  • DH
  • DHE
  • ECDHE

DH算法是什么?

DH算法是非对称加密算法,因此也可用作密钥交换,核心思想就是离散对数。

代码语言:javascript复制
# 对数运算

x = log2y

上述公式其中x为对数,y为真数,底为2。对于上述例子,32的对数是5,64的对数是6,可以看出对数的取值是能够连续的。

但是离散对数的取值是无法连续,离散也是因此得名。

代码语言:javascript复制
a ^ i (mod p) = b

对于一个整数b和一个质数p的一个原根a,能够找到唯一一个指数i使得上述公式成立,那么指数i称为b的以a为底数的模p的离散对数。

底数a和和模p是离散对数的公开参数,b是真数,i是对数,知道了对数i我们很轻松就能算出真数b,但是如果知道真数b但是很难计算对数i,尤其是模p很大的时候,现有的计算机的计算能力是无法破解的。

DH算法如何交换密钥

  1. 客户端(称为小c)和服务端(称为小s)需要交换密钥,首先需要确定公开参数底数g和模p。
  2. 客户端小c和服务端小s分别生成一个随机数作为私钥(分别称为小a和小b),在根据底数a和模p即可计算出各自的公钥(称为大A和大B):

小c的公钥为A:A = g ^ a (mod p) 小s的公钥为B: B = g ^ b (mod p)

可以看出我们通过私钥生成公钥很容易,但是通过公钥逆向计算私钥绝对是地狱级别的困难,如果您能算出来说不定你就是未来量子(手动狗头)。

双方交换公钥以后,客户端小c有:

  • A:客户端公钥
  • a:客户端私钥
  • B:服务端公钥
  • g
  • p

服务器端小s有:

  • A:客户端公钥
  • b:服务端私钥
  • B:服务端公钥
  • g
  • p

客户端小c会做以下计算:

K = B ^ a (mod p)

服务端小s会做以下计算:

K = A ^ b (mod p)

由于离散对数具有幂的交换律,因此客户端和服务端计算出来的K值就是相等的,这个K就是对称加密密钥。

DH算法的种类

目前有两种:

  • static DH
  • DHE

static DH就是有一方私钥固定不变(通常为服务器端),虽然很难破解但是随着时间的推移还是有一定几率被破解的,不具备向前保密。

DHE就是让每次双方在进行密钥协商时,都随机生成私钥,这样每次通信过程都是独立的,即使你破解了此次的私钥,也无法破解过往的通信。

ECDHE算法是啥?

在DHE算法的基础上利用了ECC椭圆曲线的特性,用更少的计算量计算公钥。

为什么需要ECDHE算法

DHE算法由于需要大量的乘法运算,计算性能不高,所以出现了ECDHE算法来替代他。

ECDHE算法密钥交换过程

  1. 客户端和服务端确定好使用哪种椭圆曲线以及曲线上的基点G,这个对外公开
  2. 客户端和服务端各自生成一个私钥(假设分别为c和s),将私钥与基点G相乘可以分别得到其公钥(假设分别为CP和SP)
  3. 双方交换公钥,最后服务器计算(x1,y1)= CP * s,客户端计算(x2,y2)= c * SP,由于椭圆曲线的满足交换律和结合律,所以(x1, y1)= CP * s = s * c * G = c * s * G = c * SP = (x2, y2),因此(x1,y1)和(x2, y2)相等,这个坐标即可当做对称密钥。

基于ECDHE密钥协商算法的TLS1.2握手分析

客户端发起第一次握手请求这个采用RSA协商算法的握手无区别,这里就不说了。

TLS第二次握手

当服务端进行响应,进行第二次握手就可以有区别了,主要有两步如下图:

首先回应ServerHello消息,如下:

这里使用TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256密码套件,说明我们的密钥协商算法要使用ECDHE。

然后第二步中先是发送证书给客户端以示清白,紧接着这里就和之前RSA密钥协商的TLS握手有区别了,这里会发送Server Key Exchange的消息,我们看一下消息内容:

  • Curve Type:选取了名为named_curve的椭圆曲线,选好椭圆曲线相当于基点G也好了
  • Pubkey:根据基点G和服务器生成的私钥计算出的公钥
  • Signature:为了保证这个椭圆曲线的公钥不被第三方篡改,服务端会用RSA签名算法给服务端的椭圆曲线公钥做个签名。

最后服务端在发送一个Server Hello Done消息,告诉客户端这是我提供的信息。

目前客户端和服务端已经共享了两个随机数、使用的椭圆曲线,椭圆曲线基点G,服务器的椭圆公钥

TLS第三次握手

这一步客户端会发送Client Key Exchange消息,消息如下:

  • Pubkey:客户端根据服务端共享的曲线、基点加上自己的私钥计算出的公钥,该公钥会共享给服务器使用

到这里服务器和客户端又多共享了客户端公钥,按道理已经可以计算出对称密钥了,但最终的会话对称密钥为了更加安全是使用「客户端随机数 服务器随机数 椭圆曲线计算出来的共享密钥」来生成最终的会话密钥。

算好会话密钥以后,紧接着会发送一个Change Cipher Spec消息告诉服务段后续的数据我会通过会话对称密钥加密传输。

最后会发送Encrypted Handshake Message,这部分消息就是对之前发送的数据做个摘要,然后使用对称密钥加密以后传输给服务器。

第三次握手以后,不需要等待服务器的第四次握手既可以进行传输应用数据,如下图:

TLS第四次握手

服务器在收到客户端的请求后,也会发送Change Cipher Spec消息和Encrypted Handshake Message。

至此握手完成,以后数据就可以正常加密传输了。

ECDHE和RSA密钥协商算法的区别

  • RSA不支持向前保密,ECDHE支持向前保密
  • ECDHE在三次握手结束以后就可以传输应用数据,节省了一个消息的往返时间,RSA必须等待四次握手结束后才可以传输应用数据
  • ECDHE在第二次握手会发送Server Key Exchange的消息,RSA没有该消息。

目前TLS已经发展到1.3,1.3对比1.2也有了很多优化,有兴趣的读者可以去了解一下。

0 人点赞