本文在上篇文章基础上更近一步,更加深入走进TLS协议。
HTTPS=HTTP+TLS,HTTP本身没有握手过程,完成一次HTTP交互,客户端和服务端只要一次请求/响应即可完成。
TCP确实需要握手建立连接,但是站在HTTP层的高度确实不存在握手这一说。
但是引入TLS协议后,需要进行多次交互才能进行后续的加密过程,这里交互的过程实际上是一个协商的过程,比如客户端告知服务器端其支持的密码套件,服务器端从中选择双方都支持的密码套件。
本文知识点与前文多篇文章关联,并且更进一步,还请充分理解前文,本文也是下篇文章对HTTPS抓包分析的重要前置文章。
一、HTTPS整体流程说明
在宏观上学习了TLS协议后,我们总结下HTTPS整体流程,HTTPS设计十分巧妙,主要分为握手层和加密层。
握手层位于加密层的上层,密钥块等加密信息正是由握手层提供给加密层的,对于一个HTTPS请求来说,HTTP消息在没完成握手之前,是不会传递给加密层的,只有握手成功,最终应用层的HTTP消息都会交由加密层进行加密。
(1)握手层
客户端与服务端交互一些信息,比如随机数、密码套件等信息,该密码套件需要得到双方认可,客户端通过服务器发送的证书确认服务器身份后,双方开始密钥协商,最终协商出预备主密钥、主密钥、密钥块。有了能用于加密算法和MAC算法等需要的密钥块后,接下来消息交给加密层去加密。
(2)加密层
加密层有了握手层提供的密钥块,就可以进行机密性和完整性保护了。
因此核心是在握手层,也正是TLS协议的灵魂,握手分为好几个步骤,我们来分别看看。
HTTPS的完整处理流程如下,分别画出了基于RSA和DHE的密钥协商算法的交互流程:
只是画出了抽象流程,下篇文章将结合抓包匹配实际交互报文的细节,本文的作用是为了分析HTTPS报文而准备,上图利于理解使用,下面针对流程图进行说明。
二、握手之身份认证
第一步是做服务器身份认证,避免中间人攻击问题。
这个我们已经学习过,通过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协议中最重要的一个概念,上篇文章我们已经简单说明过。
密码套件用来决定本次连接中客户端和服务端采用的加密算法、HMAC算法、密钥协商算法等各类算法。
密码套件是在握手阶段进行协商的,比如客户端告知服务器其支持的密码套件,服务器从中选择一个双方都支持的密码套件,这样双方达成一致采用都支持的算法来处理。
为什么每次都要协商密码套件呢?不能固定吗?有很多苦衷:
-
客户端环境多变,比如浏览器版本、操作系统都不一样,可能客户端不支持某种算法,因此必须要协商出来双方都认可的算法;
-
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算法。
四、握手之密钥协商
有了密码套件后,下面就是使用协商好的密钥协商算法进行密钥协商。
目前主流的密钥协商算法是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算法。
五、握手之完整性校验
以RSA密钥协商算法为例,客户端生成预备主密钥,然后进行加密发送给服务器端,不过前文一直强调,有加密的地方就有完整性校验,避免消息被中间人篡改。
读者朋友们可能会纳闷:不是有身份认证了吗,为什么还存在中间人攻击?
确实,证书验证可以确保服务器真实身份,但是密钥协商是身份认证之后的过程,攻击者无法攻击身份校验过程,但是可以在后续的握手过程中篡改消息。
如何避免握手消息被篡改呢?
我们已经知道,在握手结束后,无论是RSA密钥协商算法还是DH密钥协商算法,都会生成密钥块,生成好后进行握手消息的完整性校验:
-
客户端将发送和接收到的所有握手消息组合在一起,然后计算出摘要数据,握手层使用密钥块对摘要数据进行加密和完整性保护,然后发送给服务器(算总账能不能对的上)。
-
服务器接收到验证消息后,使用加密块解密出摘要数据。
-
紧接着服务器自行计算发送和接收的所有握手消息,再计算出消息的摘要数据,如果摘要数据和解密出的摘要数据相同,代表客户端发送的消息没有被篡改。(总账能对得上)
同理,服务器端也要计算验证消息,然后发送给客户端进行校验,步骤和上述的过程类似,需要注意的是,客户端和服务器端计算的摘要数据是不一样的,因为双方发出和收到的消息并不一样,顺序也不一样。
总之,握手消息会经过TLS协议加密层保护,能够确保握手消息是经过机密性和完整性处理的,如果攻击者篡改握手消息, 整个握手过程会失败。
握手成功后,加密层的处理就比较单纯的,使用握手层协商出来的加密层所需要的算法和对应的密钥块,接下来进行加密运算和完整性保护,就不再赘述了。
花了两篇介绍TTLS协议,但是仍然未提及TLS协议的握手细节,目前已经准备充分,下篇文章结合对HTTPS的抓包流程来实际看TLS协议的交互流程。
本文完,下篇见!
原文始发于微信公众号(幕后哈土奇):七十二、进阶篇-浅谈TLS协议(下篇)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/113107.html