七十二、进阶篇-浅谈TLS协议(下篇)

本文在上篇文章基础上更近一步,更加深入走进TLS协议。

HTTPS=HTTP+TLS,HTTP本身没有握手过程,完成一次HTTP交互,客户端和服务端只要一次请求/响应即可完成。

TCP确实需要握手建立连接,但是站在HTTP层的高度确实不存在握手这一说。

但是引入TLS协议后,需要进行多次交互才能进行后续的加密过程,这里交互的过程实际上是一个协商的过程,比如客户端告知服务器端其支持的密码套件,服务器端从中选择双方都支持的密码套件。

本文知识点与前文多篇文章关联,并且更进一步,还请充分理解前文,本文也是下篇文章对HTTPS抓包分析的重要前置文章。

七十二、进阶篇-浅谈TLS协议(下篇)

一、HTTPS整体流程说明

在宏观上学习了TLS协议后,我们总结下HTTPS整体流程,HTTPS设计十分巧妙,主要分为握手层和加密层。

七十二、进阶篇-浅谈TLS协议(下篇)

握手层位于加密层的上层,密钥块等加密信息正是由握手层提供给加密层的,对于一个HTTPS请求来说,HTTP消息在没完成握手之前,是不会传递给加密层的,只有握手成功,最终应用层的HTTP消息都会交由加密层进行加密。

(1)握手层

客户端与服务端交互一些信息,比如随机数、密码套件等信息,该密码套件需要得到双方认可,客户端通过服务器发送的证书确认服务器身份后,双方开始密钥协商,最终协商出预备主密钥、主密钥、密钥块。有了能用于加密算法和MAC算法等需要的密钥块后,接下来消息交给加密层去加密。

(2)加密层

加密层有了握手层提供的密钥块,就可以进行机密性和完整性保护了。

因此核心是在握手层,也正是TLS协议的灵魂,握手分为好几个步骤,我们来分别看看。

HTTPS的完整处理流程如下,分别画出了基于RSA和DHE的密钥协商算法的交互流程:

七十二、进阶篇-浅谈TLS协议(下篇)

七十二、进阶篇-浅谈TLS协议(下篇)

只是画出了抽象流程,下篇文章将结合抓包匹配实际交互报文的细节,本文的作用是为了分析HTTPS报文而准备,上图利于理解使用,下面针对流程图进行说明。

七十二、进阶篇-浅谈TLS协议(下篇)

二、握手之身份认证

第一步是做服务器身份认证,避免中间人攻击问题。

这个我们已经学习过,通过PKI技术来证明服务器,其核心是证书,复习下浏览器如何校验身份的:

  • 浏览器向服务器端发送连接请求,访问的是https://www.example.com;

  • 服务器收到请求后,将【证书文件】和【服务器RSA密钥对的公钥】发送给浏览器;

  • 浏览器收到证书文件,从中判断是哪个CA机构签发的证书,也获取了证书签名算法,由于浏览器内置了该CA机构的根证书,根证书包含了CA机构的公钥,用于验签;

  • 通过内嵌的CA机构根证书的公钥验签,验签成功说明此证书是合法CA机构签发的;(忽略了证书链等细节,详情见第70篇文章)

  • 浏览器紧接着校验证书申请者身份,从证书中取出RSA公钥和主机名,注意这里的RSA公钥就是【服务器RSA密钥对的公钥】,注意不要混淆为CA机构的公钥;

  • 浏览器判断主机名确实就是要访问的www.example.com,并且从连接阶段获取到的服务器的RSA公钥与证书中包含的RSA公钥是一致的话,则表示浏览器成功校验了服务器身份,连接的服务器确实是www.example.com主机的拥有者;

总之,如果认证通过,浏览器则会拿到服务器的公钥。

七十二、进阶篇-浅谈TLS协议(下篇)

三、握手之密码套件协商

密码套件是TLS协议中最重要的一个概念,上篇文章我们已经简单说明过。

密码套件用来决定本次连接中客户端和服务端采用的加密算法、HMAC算法、密钥协商算法等各类算法。

密码套件是在握手阶段进行协商的,比如客户端告知服务器其支持的密码套件,服务器从中选择一个双方都支持的密码套件,这样双方达成一致采用都支持的算法来处理。

为什么每次都要协商密码套件呢?不能固定吗?有很多苦衷:

  • 客户端环境多变,比如浏览器版本、操作系统都不一样,可能客户端不支持某种算法,因此必须要协商出来双方都认可的算法;

  • TLS协议也在不断升级,必须要协商一个双方都能接受的协议版本,避免不同版本差异导致握手失败;

  • 密码学算法也在不断进步,采取协商的方式方便升级双方算法;

  • 协商不仅仅是协商密码套件,每次连接时客户端和服务端还要分别告知对方自己生成的随机数,用来生成动态密钥块,这个随机数很重要;

  • 等等…

密码套件的构成例子:

七十二、进阶篇-浅谈TLS协议(下篇)

包含如下:

  • 密钥协商算法

  • 身份验证算法

  • 数据加密算法

  • HMAC算法或PRF算法(上文提及的密钥衍生算法)

密码套件格式并无统一标准,我们来看几个典型结构。

(1)TLS_DH_RSA_WITH_AES_CBC_128_SHA

  • DH:表示密钥协商算法,用来协商预备主密钥,服务器会将DH参数和DH公钥发给客户端;

  • RSA:身份认证算法,表示证书中包含的服务器公钥是RSA公钥;

  • AES_CBC_128:表示加密算法,用来保证机密性,AES是对称加密算法、加密模式是CBC、密钥长度是128比特;

  • SHA:表示HMAC算法,用于保证完整性,本例是HMAC_SHA1算法;

(2)TLS_RSA_WITH_AES_CBC_128_SHA

密钥协商算法和身份验证算法都采用RSA算法,也就是说服务器公钥是RSA公钥,密钥协商算法采用的也是RSA算法,其他无区别。

(3)TLS_ECDHE_WITH_ECDSA_AES_256_GCM_SHA384

  • ECDHE:表示密钥协商算法采用ECDHE;

  • ECDSA:表示服务器公钥是ECDSA;

  • AES_256_GCM:AES是对称加密算法、加密模式是GCM、密钥长度是256比特;

  • PRF算法:TLS1.2版本使用的PRF算法加密基元默认是SHA256算法,这里采取了更加安全的SHA384算法;

这里AES_256_GCM比较特殊,GCM模式是属于一种叫做AEAD模式,AEAD加密模式在底层组合了加密算法和MAC算法,能够同时保证数据机密性和完整性,减轻了使用者的负担。因此AEAD加密模式不用处理HMAC算法。

七十二、进阶篇-浅谈TLS协议(下篇)

四、握手之密钥协商

有了密码套件后,下面就是使用协商好的密钥协商算法进行密钥协商。

目前主流的密钥协商算法是DHE算法和ECDHE算法,DHE相对于DH算法多了一个E,这里的E指的是Ephemeral,短暂的意思,这里指密钥是短暂的,每次握手都会协商出一个新的预备主密钥,即使密钥泄露,攻击者也不能获取到前面已经加密过的数据,这叫做前向安全性。

前向安全性是 TLS 协议中非常重要的一个概念,对于不支持前向安全性的密码套件,攻击者能够记录所有过去发生的加密数据,当某一天服务器的私钥泄露,攻击者就可以使用泄露的私钥解密过去的加密数据。

推荐使用支持前向安全性的密码套件,主要原因在于密钥协商算法不依赖于服务器的密钥(比如 RSA 密钥对),服务器密钥仅仅用于证书身份认证,不会参与密钥协商,预备主密钥的生成和服务器关系密钥并不大(此处划重点

而不支持前向加密的密码套件,协商出的预备主密钥能被服务器私钥解密,一旦私钥泄露,加密数据就有可能被解密。

还记得上篇文章对比的RSA和DH协商算法的密钥生成流程吗?这里解释了为什么DH密钥协商算法虽然比RSA协商算法多很多步骤,但是仍然使用DH的原因,我们再来强化下印象:

  • RSA算法

    • 客户端向服务器端发起连接请求,服务器端发送 RSA 密钥对的公钥给客户端;

    • 客户端通过随机数生成器生成一个预备主密钥,用服务器的公钥加密并发送给服务器端;

    • 服务器解密预备主密钥,假如能够正确解密,则说明客户端和服务器端共同协商出一个预备主密钥;

  • DH算法

    • 客户端向服务器端发起连接请求;

    • 服务器端生成 RSA 密钥对,并将公钥发送给客户端,客户端依靠证书链来验证身份,确保公钥确实来自真实服务器

    • 服务器端生成 DH 参数和服务器 DH 密钥对,用 RSA 私钥签名 DH 参数和服务器 DH 公钥,最后将签名值、 DH 参数 、服务器 DH 公钥发送给客户端;

    • 客户端通过服务 RSA 的公钥验证签名,获取到 DH 参数和服务器 DH 公钥;

    • 客户端通过 DH 参数生成客户端 DH 密钥对,并将客户端 DH 公钥发送给服务器端;

    • 客户端通过客户端 DH 私钥和服务器端 DH 公钥计算出预备主密钥;

    • 服务器端接收到客户端的 DH 公钥,结合服务器的 DH 私钥计算出预备主密钥;

    • 最终客户端和服务器端计算出的预备主密钥能够保持一致;

TLS协议在没有ECC之前一般使用DHE密码套件支持前向安全,但是DHE算法运算非常缓慢,并且密钥长度过短的DHE算法也会存在安全问题,所以引入ECC椭圆曲线提高处理性能和安全性,形成了主流的ECDHE算法。

七十二、进阶篇-浅谈TLS协议(下篇)

五、握手之完整性校验

以RSA密钥协商算法为例,客户端生成预备主密钥,然后进行加密发送给服务器端,不过前文一直强调,有加密的地方就有完整性校验,避免消息被中间人篡改。

读者朋友们可能会纳闷:不是有身份认证了吗,为什么还存在中间人攻击?

确实,证书验证可以确保服务器真实身份,但是密钥协商是身份认证之后的过程,攻击者无法攻击身份校验过程,但是可以在后续的握手过程中篡改消息

如何避免握手消息被篡改呢?

我们已经知道,在握手结束后,无论是RSA密钥协商算法还是DH密钥协商算法,都会生成密钥块,生成好后进行握手消息的完整性校验:

  • 客户端将发送和接收到的所有握手消息组合在一起,然后计算出摘要数据,握手层使用密钥块对摘要数据进行加密和完整性保护,然后发送给服务器算总账能不能对的上

  • 服务器接收到验证消息后,使用加密块解密出摘要数据。

  • 紧接着服务器自行计算发送和接收的所有握手消息,再计算出消息的摘要数据,如果摘要数据和解密出的摘要数据相同,代表客户端发送的消息没有被篡改。(总账能对得上

同理,服务器端也要计算验证消息,然后发送给客户端进行校验,步骤和上述的过程类似,需要注意的是,客户端和服务器端计算的摘要数据是不一样的,因为双方发出和收到的消息并不一样,顺序也不一样。

总之,握手消息会经过TLS协议加密层保护,能够确保握手消息是经过机密性和完整性处理的,如果攻击者篡改握手消息, 整个握手过程会失败

握手成功后,加密层的处理就比较单纯的,使用握手层协商出来的加密层所需要的算法和对应的密钥块,接下来进行加密运算和完整性保护,就不再赘述了。

花了两篇介绍TTLS协议,但是仍然未提及TLS协议的握手细节,目前已经准备充分,下篇文章结合对HTTPS的抓包流程来实际看TLS协议的交互流程

本文完,下篇见!

原文始发于微信公众号(幕后哈土奇):七十二、进阶篇-浅谈TLS协议(下篇)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/113107.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!