TLSorSSL协议

TLS概述

TLS(传输层安全性)协议基于SSL(安全套接字层)协议,该协议最初由Netscape开发,用于增强Internet上的电子商务安全性。SSL是在应用程序级实现的,直接位于TCP(传输控制协议)之上,允许更高级别的协议(如HTTP或电子邮件协议)无需更改即可正常工作。如果正确配置了SSL,则第三方观察者只能找到连接参数(例如,使用的加密类型),以及传输频率和大概数据量,但无法读取和更改它们。
Internet协议栈中TLS(SSL)的具体位置如图所示:

在IETF(Internet工程任务组)标准化SSL协议后,它被重命名为TLS。因此,尽管名称SSL和TLS是可互换的,但它们仍然不同,因为每个描述了协议的不同版本。

该协议的第一个发布版本称为SSL 2.0,但由于发现了漏洞,因此很快被SSL
3.0取代。如前所述,SSL是由Netscape开发的,因此在1999年1月,IETF以TLS
1.0的名称公开标准化。然后在2006年4月,发布了一个版本的TLS
1.1,它扩展了协议的原始功能并涵盖了已知的漏洞。目前的协议版本是TLS
1.2,于2008年8月发布。

如前所述,TLS旨在用于TCP,但是为了使用UDP(用户数据报协议)等数据报协议,开发了一种特殊版本的TLS,称为DTLS(数据报传输层安全性)。

加密,身份验证和完整性

TLS协议旨在为所有正在使用它的应用程序提供三种服务,即:加密,身份验证和完整性。从技术上讲,并非所有三种都可以使用,但在实践中,为了确保安全,通常使用所有三种:

  • 加密 - 隐藏从一台计算机传输到另一台计算机的信息;

  • 身份验证 - 验证传输信息的作者身份;

  • 诚信 - 检测信息的伪造。

为了建立加密安全数据通道,连接节点必须就所使用的加密方法和密钥达成一致。TLS协议唯一标识此过程,更多内容在TLS
Handshake中进行了讨论。应当注意,TLS使用公钥加密,其允许节点在没有彼此任何先验知识的情况下建立共享秘密加密密钥。

同样在TLS握手过程的框架中,可以建立客户端和服务器的身份的真实性。例如,客户可以确定向他提供有关银行帐户信息的服务器实际上是银行服务器。反之亦然:公司的服务器可以确定连接到它的客户是公司的员工,而不是局外人(这种机制称为信任链,将在相应的部分讨论)。

最后,TLS提供每个消息的发送MAC(消息认证码)代码,其创建算法是单向加密散列函数(实际上是校验和),其密钥对于两个通信参与者都是已知的。每次发送消息时,都会生成其MAC值,该值也可以由接收方生成,这可以确保信息的完整性并防止其替换。

因此,简要考虑了TLS协议的加密安全性的所有三种机制。

握手

在通过TLS开始数据交换之前,客户端和服务器必须就连接参数达成一致,即:所使用协议的版本,数据加密方法,并在必要时检查证书。启动连接的方案称为TLS
Handshake,如图所示:

让我们更详细地分析此过程的每个步骤:

  1. 由于TLS正在使用TCP,因此首先在客户端和服务器之间建立TCP连接。

  2. 安装TCP后,客户端以明文形式将规范发送到服务器(即,它要使用的协议版本,支持的加密方法等)。

  3. 服务器批准所使用协议的版本,从提供的列表中选择加密方法,附加其证书并向客户端发送响应(如果需要,服务器也可以请求客户端证书)。

  4. 此时的协议版本和加密方法被视为已批准,客户端检查发送的证书并启动RSA或Diffie-Hellman密钥交换,具体取决于所设置的参数。

  5. 服务器处理客户端发送的消息,验证MAC,并以加密形式向客户端发送最终(”完成”)消息。

  6. 客户端解密收到的消息,检查MAC,如果一切正常,则认为连接已建立,应用程序数据交换开始。

显然,建立TLS连接通常是一个漫长而耗时的过程,因此TLS标准中有几个优化。特别是,有一个称为”缩写握手”的过程,它允许您使用先前商定的参数重新连接(当然,如果客户端和服务器过去已经建立了TLS连接)。在”恢复会话”项中更详细地讨论了该过程。

握手过程还有一个额外的扩展,称为TLS False
Start。此扩展允许客户端和服务器在加密方法建立后立即开始交换加密数据,这减少了一次迭代消息的连接建立。这在”TLS
False Start”中有更详细的讨论。

TLS密钥交换

=由于各种历史和商业原因,TLS使用RSA算法最常使用密钥交换:客户端生成对称密钥,使用服务器的公钥对其进行签名,然后将其发送到服务器。反过来,使用私钥解密服务器上的客户端密钥。在此之后,密钥交换被宣布完成。该算法有一个缺点:同一对公钥和私钥也用于服务器认证。因此,如果攻击者获得对服务器私钥的访问权,他就可以解密整个通信会话。此外,攻击者可以简单地以加密版本记录整个通信会话,并在以后可以获得服务器的私钥时进行解密。与此同时,Diffie-Hellman密钥交换似乎更安全,因为安装的对称密钥永远不会离开客户端或服务器,因此,即使他知道服务器的私钥,也不会被入侵者截获。降低过去通信会话危害的风险的服务基于:对于每个新的通信会话,创建新的所谓的”临时”对称密钥。因此,即使在最坏的情况下(如果攻击者知道服务器的私钥),攻击者也只能从未来的会话中获取密钥,而不能解密先前记录的密钥。所谓的”临时”对称密钥。因此,即使在最坏的情况下(如果攻击者知道服务器的私钥),攻击者也只能从未来的会话中获取密钥,而不能解密先前记录的密钥。所谓的”临时”对称密钥。因此,即使在最坏的情况下(如果攻击者知道服务器的私钥),攻击者也只能从未来的会话中获取密钥,而不能解密先前记录的密钥。

目前,所有浏览器在建立TLS连接时,更喜欢Diffie-Hellman算法的组合和临时密钥的使用,以提高连接的安全性。

应该再次注意,公钥加密仅在初始连接建立期间的TLS握手过程中使用。配置隧道后,对称加密开始起作用,并使用指定的对称密钥加密当前会话中的通信。这对于提高性能是必要的,因为公钥加密需要更多的计算能力。

恢复TLS会话

如前所述,完整的TLS握手过程在计算成本方面非常冗长且昂贵。因此,开发了一个过程,允许您根据已配置的数据恢复先前中断的连接。

从协议的第一个公共版本(SSL
2.0)开始,TLS握手内的服务器(即,初始ServerHello消息)可以生成并发送32字节的会话标识符。当然,在这种情况下,服务器为每个客户端存储生成的标识符和会话参数的缓存。反过来,客户端存储发送的ID,并在初始ClientHello消息中包含它(当然,如果存在)。如果客户端和服务器都具有相同的会话标识符,则使用图中所示的简化算法建立公共连接。如果没有,则需要完整版的TLS握手。

会话续订过程允许您跳过对称密钥的生成,这会显着增加连接建立时间,但不会影响其安全性,因为使用了先前会话中先前未妥协的数据。

然而,存在实际限制:由于服务器必须存储关于所有打开会话的数据,这导致数千和数百万客户同时请求的流行资源的问题。

为了避免这个问题,开发了一个”会话票证”机制,它消除了在服务器上存储每个客户端数据的需要。如果客户端在初始连接建立期间表明它支持该技术,则TLS握手期间服务器向客户端发送所谓的会话票证

使用服务器私钥加密的会话参数。下次会话恢复时,客户端会发送会话票证和ClientHello。因此,服务器不需要存储关于每个连接的数据,但是连接仍然是安全的,因为会话票证使用仅在服务器上已知的密钥加密。

TLS错误启动

会话恢复技术无疑会提高协议性能并降低计算成本,但是,它不适用于与服务器的初始连接,或者在前一个会话已经过期的情况下。

为了获得更好的性能,开发了TLS False
Start技术,这是一个可选的协议扩展,允许您在TLS握手仅部分完成时发送数据。详细的TLS
False Start方案如图所示:

重要的是要注意TLS False
Start不会改变TLS握手过程。它基于这样的假设:在客户端和服务器已经知道连接参数和对称密钥的那一刻,可以已经发送应用程序数据,并且可以并行执行所有必要的检查。因此,连接已准备好使用之前的一个消息传递迭代。

TLS信任链

身份验证是每个TLS连接的组成部分。考虑Alice和Bob之间最简单的身份验证过程:

  1. Alice和Bob都生成自己的公钥和私钥。

  2. Alice和Bob交换公钥。

  3. Alice生成一条消息,用她的私钥对其进行加密,并将其发送给Bob。

  4. Bob使用从Alice接收的密钥来解密消息,从而验证所接收消息的真实性。

显然,这个方案建立在Alice和Bob之间的信任基础上。假设公钥的交换发生在例如个人会议期间,因此Alice确信她直接从Bob接收到密钥,而Bob又确信她收到了Alice的公钥。

现在让爱丽丝收到查理的消息,她不熟悉,但声称自己是鲍勃的朋友。为了证明这一点,Charlie要求他提前用Bob的私钥签署他自己的公钥,然后将这个签名附加到给Alice的消息上。Alice首先检查Bob在Chalie的密钥上的签名(她能够做到这一点,因为Bob的公钥已经知道),确保Charlie真的是Bob的朋友,接受他的消息并执行已知的完整性检查,确保消息来自Charlie

前一段中描述的是创建”信任链”(或”信任链”,如果是英语)。
在TLS协议中,信任链数据基于由特殊机构提供的真实性证书,称为证书颁发机构(CA)。证书颁发机构进行检查,如果颁发的证书被泄露,则该证书将被撤销。

从颁发的证书形成已经被认为是一个信任链。它的根源是所谓的”根CA证书” -
由大型中心签署的证书,其可信度是无可争辩的。通常,信任链看起来像这样:

当然,有些情况下必须撤销或撤销已颁发的证书(例如,证书的私钥被泄露,或整个认证程序受到损害)。为此,真品证书包含有关检查其相关性的特殊说明。因此,在构建信任链时,有必要检查每个信任节点的相关性。

这种检查的机制很简单,它基于所谓的。”证书撤销清单”(CRL)。每个证书颁发机构都有此列表,这是一个简单的已撤销证书序列号列表。因此,任何想要验证证书真实性的人只需下载该列表并搜索要检查的证书号。如果找到该号码

  • 则表示该证书已被撤销。

显然存在一些技术上的不合理性:要仅检查一个证书,需要请求整个撤销证书列表,这会导致速度变慢。为了解决这个问题,开发了一种称为证书证书状态协议(OCSP)的机制。它允许您动态检查证书状态。当然,这减少了网络带宽的负担,但同时也产生了几个问题:

  • CA必须处理实时工作负载;

  • 证书颁发机构必须始终确保其可用性;

  • 由于实时请求,证书颁发机构会收到有关每个用户访问过哪些站点的信息。

实际上,在所有现代浏览器中,两种解决方案(OCSP和CRL)相互补充,而且,通常,可以自定义用于检查证书状态的首选策略。

追踪TCP流

       
TLS/SSL建立在应用层和传输层TCP之间,将到达TCP前的数据都进行加密处理,前面做了那么多的工作,握手密钥协商,数字签名防抵赖等,都是为了保证数据的完整性和机密性。HTTP结合TLS/SSL协议就是HTTPS,如果HTTP消息不交由TLS/SSL协议,一旦流量被截获了,最大的问题就是隐私泄露,
如果我们在一个没有部署HTTPS的网站上登陆我们的信息,以HTTP流量方式进行发送,由于明文传输的原因,一旦请求被截获,里面的内容就泄露了。路由选择让这些报文分组经过很多节点设备,在这些节点路由中等待分组转发的报文都有可能被截获然后篡改,虽然TCP能够保证数据正确到达通信双方处,但不能保证数据是正确的没有被篡改的,对于没有使用TLS/SSL的服务器来说,只要收到的HTTP请求格式是正确的,就会给予响应。像下面这样情况:

       
如果我们在一个HTTP页面传输数据,例如在一个登陆页面,输入自己的用户名和密码并发送给服务器,中途流量被截获了,直接泄露了我们发送的数据,像上图一样。而如果我们在部署了HTTPS的网站上登陆,因为数据在到达TCP前就交由TLS/SSL协议进行加密,之后再发送,所以中间流量被截获后,看到的也是经过加密的密文:

       
可以看到,用户名和密码都是一串乱码。拿DH密钥协商举例,客户端和服务器端经过密钥协商后得到对方的公钥,使用公钥加密后的密文仅对方的私钥可以解出明文,所以即使在流量发送过程中被截获了,也能保证数据不泄露。

       
除了数据未加密的问题外,身份校验也是一个问题,在部署了HTTPS的网站中,CA机构会为其签发一张证书,证书里面包含了一些服务器的关键信息,例如服务器公钥,主机名等,CA机构用自己的RSA私钥对该证书进行签名,浏览器因为对CA机构的信任,通常内嵌CA机构的公钥,在身份校验时,服务器向客户端发送自己的证书,浏览器使用CA公钥验证证书签名,成功后,即可使用里面的服务器公钥进行密钥协商。

       
TLS/SSL协议做的东西很多,前面的日志里也总结了大致的步骤,还有各个子协议,子消息和扩展项,接下来抓一下HTTPS流量,看看一个网址从建立连接开始,到会话恢复等各部分内容,分析下整个TLS的处理过程。

捕获HTTPS流量

       
首先打开一个HTTPS网页,就拿CSDN首页为例吧,打开网站后,我们抓取过程中的HTTPS流量,看看使用TLS协议的网站在客户端(浏览器)和服务器端建立连接过程中发送交换的各个子消息:

        可以看到,我们访问一个HTTPS网站时,使用了TLS
v1.2版本协议,经历了握手协议过程,

1、 首先由客户端发送Client Hello子消息,然后服务器端回应ServerHello。

2、
接着由服务器(注意看前面,服务器ip为47.95.47.253)发送证书Certificate,Certificate
Status扩展供证书吊销状态校验,Server Key
Exchange子消息表示进行密钥协商的一部分,例如使用DH密钥协商,服务器需要向客户端发送自己的DH参数和DH公钥,所以通过该子消息来传递。最后发送Server
Hello Done。

3、 客户端在收到Server Hello Done后,回应Client Key
Exchange进行密钥协商(例如根据服务器发来的DH参数生成客户端DH密钥对,然后通过Client
Key Exchange子消息把客户端公钥发送给服务器端,完成密钥协商),Change
Cipher
Spec子消息表示TLS记录层需要的加密参数都准备好,可以切换连接状态为可读和可写状态。最后的Encrypted
Handshake Message子消息就是Finished子消息,用来校验握手消息没有被篡改。

4、 最后是由服务器发送Change Cipher Spec和Encrypted Handshake
Message,注意上图中服务器还发送了New Session
Ticket,表明了本次会话可以使用Session
Ticket方式进行会话恢复。待服务器发送完Finished子消息后,接下来的应用层数据都可以进行加密处理了。

Client Hello

        按照前面我们说过的,Client
Hello子消息中包含有客户端支持的密码套件(用于协商),扩展项等,下面查看下Client
Hello子消息里的详细内容:

        可以看到,最上面Record Layer:Handshake
Protocol,由TLS记录层进行了封装握手协议,握手协议中发送的子消息是Client
Hello,里面是客户端支持的最高TLS版本号v1.2,随机数Random,Session
ID和支持的密码套件,可以看到支持的妈咪套件由17个,优先支持的是TLS_AES_128_GCM_SHA256(0x1301)。

       
往下看还有客户端的扩展项,server_name表示客户端使用了SNI服务器名称指示扩展,告诉服务器请求访问的主机名,让服务器发送相应的证书供校验。session_ticket扩展就是告诉服务器请求使用SessionTicket方式进行会话恢复,第一次建立完整TLS握手时,客户端发送的该扩展是空的,由服务器决定是否支持SessionTicket。status_request扩展也是以前总结过,如果校验证书吊销状态方式使用OCSP在线证书状态协议,那么就是发送该扩展,如果使用OCSP套封,即由服务器来发送OCSP请求,获取响应后,服务器再向客户端发送CertificateStaus子消息,里面包含了证书吊销状态信息。还有一个signed_certificate_timestamp扩展表示支持证书透明度机制,由CA机构或服务器实体提交,Certificate
Logs返回一个SCT信息,相当于也是一个票据,客户端再TLS/SSL协议握手阶段获取该SCT信息,证明该证书是经过监控和审计的。

Server Hello

接下来看服务器端回应的Server Hello:

        可以看到,常规的TLS版本号,随机数信息,值得注意的是Session
ID为0,表明在本次握手中,服务器端选择了不使用Session
ID进行会话恢复,从上面Client Hello和Server
Hello中都看到空的session_ticket扩展项,表明服务器端支持也选择使用SessionTicket进行会话恢复,所以弃用了Session
ID。

Certificate

       
往下走,由服务器端发送Certificate证书供客户端进行校验,从证书信息中我们可以看到,除了服务器实体证书外,还有一个中间证书:

       
第一个证书是我们的服务器实体证书,也就是CSDN的服务器,commonName=*.csdn.net。证书版本v3,序列号信息,还有使用的证书签名算法为sha256WithRSA。下面的validity标识证书的有效期,从2018-11-07到2020-11-06,还有一个值得注意的重要信息是服务器公钥,subjectPublicKey。第二个证书是中间证书,由GeoTrust
RSA
CA机构签发,详细信息就不展示出来了,有兴趣的大家可以去抓抓CSDN的首页来看即可。

Certificate extension

       
证书中还要注意的是证书扩展项,里面有很多内容,标识该证书的作用,拿服务器实体证书为例,看看里面的扩展项都有哪些:

       
证书中有10个扩展项,authorityKeyIdentifier是CA密钥标识符,subjectKeyIdentifier则是使用者密钥标识符,subjectAltName扩展标识了服务器主机名。keyUsage扩展项比较重要,标识该证书的功能,例如digitalSignature:True表示可以进行数字签名,还有extKeyUsage扩展项,用来表示证书的使用场合,红笔圈起部分可以看到该证书可以用来进行服务器端身份校验和客户端身份校验。

       
authorityInfoAccess扩展里写有OCSP服务的地址和证书地址,basicConstraints基础约束扩展表示该证书是一张普通证书,不能使用其来签发其他证书。

Server Key Exchange

       
使用DH密钥协商方式,服务器端发送DH参数和公钥给客户端,所以需要Server Key
Exchange子消息:

        可以看到ECDH(EC
Diffie-Hellman)参数服务器公钥Pubkey,Signature签名值是服务器端对该DH参数进行签名。

Client Key Exchange

       
客户端收到服务器发送的DH参数和公钥后,使用DH参数生成自己的密钥对,保留私钥,把公钥通过Client
Key Exchange发送给服务器端,完成密钥协商:

Change Cipher Spec

        Change Cipher
Spec子消息很简单,作用是告诉服务器端,客户端需要的加密参数都准备好了,客户端的TLS记录层协议可以对数据进行加密了,将连接状态由待读状态和待写状态切换为可读状态与可写状态:

Encrypted Handshake Message(Finished)

        自己的密钥块准备好,发送了Change Cipher
Spec后,再给对方发送Finished供校验所有的握手消息是没有被篡改的:

上为客户端发送,下为服务器端发送。

捕获会话恢复

        前面说过会话恢复有两种方式,Session ID和Session
Ticket两种,这里我以常用的Session
Ticket方式为例,抓包一下HTTPS流量,看看这Session
Ticket恢复方式过程中都发送了哪些子消息。

        我抓的是简书网站的HTTPS流量,看看第一次建立完整TLS握手的过程:

        可以看到,第一次完整的TL握手,Client Hello和Server
Hello(如果服务器支持)子消息中都会带有空的session_ticket扩展项,服务器端最后会发送New
Session Ticket子消息,里面保存了本次会话的一些信息:

       
例如票据的有效期Lifetime为300秒,即5分钟,服务器端对票据的加密值也在里面。接下来我们关闭简书网页,再重新打开,看看它是否通过Session
Ticket方式进行会话恢复:

       
果然,第二次握手使用了简短的握手,因为采用了会话恢复方式,客户端和服务器端不需要重新进行密钥协商,故可以看到在本次握手中,服务器端没有发送Certificate证书供校验,没有发送Server
Key Exchange进行密钥协商,没有发送Server Hello
Done子消息;客户端也没有发送Client Key Exchange,双方都是直接发送Change
Cipher
Spec子消息告诉对方自己需要的加密参数已经准备好了,然后发送Finished,会话恢复完成。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!