标签:方法 version sum 扩展性 time 直接 加密算法 历史 填充
最近对TLS1.2协议处理流程进行了学习及实现,本篇文章对TLS1.2的理论知识和处理流程进行分析,TLS协议的实现建议直接看The Transport Layer Security (TLS) Protocol Version 1.2
通常我们使用TCP协议或UDP协议进行网络通信。TCP协议提供一种面向连接的、可靠的字节流服务。但是TCP并不提供数据的加密,也不提供数据的合法性校验。
我们通常可以对数据进行加密、签名、摘要等操作来保证数据的安全。目前常见的加密方式有对称加密和非对称加密。使用对称加密,双方使用共享密钥。
但是对于部署在互联网上的服务,如果我们为每个客户端都使用相同的对称加密密钥,那么任何人都可以将数据解密,那么数据的隐私性将得不到保障。
如果我们使用非对称密钥加密,客户端使用服务端的公钥进行公钥加密,服务端在私钥不泄露的情况下,只有服务端可以使用私钥可以对数据进行解密,从而保障数据的隐私性,但是非对称加密比对称加密的成本高得多。
我们可以采用对称加密和非对称加密相结合的方式实现数据的隐私性的同时性能又不至于太差。
TLS协议就是实现了这一过程安全协议。TLS是在TCP之上,应用层之下实现的网络安全方案。在TCP/IP四层网络模型中属于应用层协议。TLS协议在两个通信应用程序之间提供数据保密性和数据完整性,另外还提供了连接身份可靠性方案。
UDP则使用DTLS协议实现安全传输,和TLS协议类似。
TLS协议的前身SSL协议是网景公司设计的主要用于Web的安全传输协议,这种协议在Web上获得了广泛的应用。
微软、Google、苹果、Mozilla四家浏览器业者将在2020年终止支持TLS 1.0及1.1版。
TLS协议是一个分层协议,第一层为TLS记录层协议(Record Layer Protocol),该协议用于封装各种高级协议。目前封装了4种协议:握手协议(Handshake Protocol)、改变密码标准协议(Change Cipher Spec Protocol)、应用程序数据协议(Application Data Protocol)和警报协议(Alert Protocol)。
Change Cipher Spec Protocol
在TLS1.3被去除。
记录层包含协议类型、版本号、长度、以及封装的高层协议内容。记录层头部为固定5字节大小。
在TLS协议规定了,如接收到了未定义的协议协议类型,需要发送一个
unexpected_message
警报。
TLS 握手协议允许服务端和客户端相互进行身份验证,并在应用程序协议传输或接收其第一个字节数据之前协商协议版本、会话ID、压缩方法、密钥套件、以及加密密钥。
完整的TLS握手流程,流程如下
Client Server
ClientHello -------->
ServerHello
Certificate*
ServerKeyExchange*
CertificateRequest*
<-------- ServerHelloDone
Certificate*
ClientKeyExchange
CertificateVerify*
[ChangeCipherSpec]
Finished -------->
[ChangeCipherSpec]
<-------- Finished
Application Data <-------> Application Data
- 表示可选步骤或与实际握手情况相关。比如重建已有连接,服务端无需执行Certificate,再比如使用RSA公钥加密时,无需ServerKeyExchange。
握手协议消息必须按上面流程的发送数据进行发送,否则需要以致命错误告知对方并关闭连接。
完整的握手流程有时候也被称为2-RTT流程,即完整的握手流程需要客户端和服务端交互2次才能完成握手。
交互应用请求到响应的交互时间被称为往返时间(Round-trip Time)
握手协议的结构如下,其中协议头的ContentType固定为22
,接下来是TLS版本号,TLS1.2为0303
,最后是用2字节表示长度。
握手协议类型包含以下:
Hello Message是具体的握手协议类型内容,不同协议内容有所不同。
Hello Request
消息用于客户端与服务端重新协商握手,该消息可能由服务端在任何时刻发送。Hello Request
消息非常简单,没有其他冗余信息。
当客户端收到了服务端的Hello Request
时可以有以下4种行为:
no_renegotiation
警报。ClientHello
重新进行TLS握手。服务端发送完HelloRequest
消息,可以有以下几种行为:
HelloRequest
消息,但未收到ClientHello
时,可以通过致命连接警报关闭连接。HelloRequest
消息,必须等待握手协商处理完成后才可以继续处理应用数据消息。Finished和Certificate的握手消息验证不包括该消息的hash。
当客户端首次与服务端建立连接或需要重新协商加密握手会话时,需要将Client Hello
作为第一条消息发送给服务端。
Client Hello
消息包含了许多重要信息,包括客户端版本号、客户端随机数、会话ID、密钥套件、压缩方式、扩展字段等。
通过前4字节填写时间方式,有效的避免了周期性的出现一样的随机数。使得"随机"更加"随机"。
在TLS握手时,客户端和服务端需要协商数据传输时的加密密钥。为了保证加密密钥的安全性。密钥需要通过客户端和服务端一起生成。客户端和服务端都提供一个32位的随机数,通过该随机数使用基于HMAC的PRF算法生成客户端和服务端的密钥。
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
,密钥交换算法是DHE
,身份认证算法是RSA
,对称加密算法是AES_256_CBC,消息摘要算法是SHA256,由于RSA又可以用于加密也可以用于身份认证,因此密钥交换算法使用RSA时,只写一个RSA,比如TLS_RSA_WITH_AES_256_CBC_SHA256
客户端发送完
ClientHello
消息后,将等待ServerHello
消息。 服务端返回的任何握手消息(HelloRequest
除外)将被视为致命错误。
当服务端接收到ClientHello
,则开始TLS握手流程, 服务端需要根据客户端提供的加密套件,协商一个合适的算法簇,其中包括对称加密算法、身份验证算法、非对称加密算法以及消息摘要算法。若服务端不能找到一个合适的算法簇匹配项,则会响应握手失败的预警消息。
版本号:服务端根据客户端发送的版本号返回一个服务端支持的最高版本号。若客户端不支持服务端选择的版本号,则客户端必须发送protocol_version
警报消息并关闭连接。
若服务端接收到的版本号小于当前支持的最高版本,且服务端希望与旧客户端协商,则返回不大于客户端版本的服务端最高版本。
若服务端仅支持大于client_version的版本,则必须发送protocol_version
警报消息并关闭连接。
若服务端收到的版本号大于服务端支持的最高版本的版本,则必须返回服务端所支持的最高版本。
32位随机数:服务端生成的32位随机数,生成方式和客户端一样。服务端生成随机数的可以有效的防范中间人攻击,主要是通过防止重新握手后的重放攻击。
会话ID:用于表示客户端和服务端之间的会话。若客户端提供了会话ID,则可以校验是否与历史会话匹配。
若不匹配,则服务端可以选择直接使用客户端的会话ID或根据自定义规则生成一个新的会话ID,客户端需要保存服务端返回的会话ID当作本次会话的ID。
若匹配,则可以直接执行1-RTT握手流程,返回ServerHello后直接返回ChangeCipherSpec
和Finished
消息。
Client Server
ClientHello -------->
ServerHello
[ChangeCipherSpec]
<-------- Finished
[ChangeCipherSpec]
Finished -------->
Application Data <-------> Application Data
在Finished消息中和完整握手一样都需要校验VerifyData。
算法套件:服务端根据客户端提供的算法套件列表和自己当前支持算法进行匹配,选择一个最合适的算法组合,若没有匹配项,则使用默认的TLS_RSA_WITH_AES_128_CBC_SHA
。
TLS1.2协议要求客户端和服务端都必须实现密码套件
TLS_RSA_WITH_AES_128_CBC_SHA
压缩方式:用于和服务端协商数据传输的压缩方式。由于TLS压缩存在安全漏洞,因此在TLS1.3中已经将TLS压缩功能去除,TLS1.2算法也建议不启用压缩功能。
扩展字段:服务端需要支持接收具有扩展和没有扩展的ClientHello。服务端响应的扩展类型必须是ClientHello
出现过才行,否则客户端必须响应unsupported_extension
严重警告并中断握手。
RFC 7568要求客户端和服务端握手时不能发送
{3,0}
版本,任何收到带有协议Hello消息的一方版本设置为{3,0}
必须响应protocol_version
警报消息并关闭连接。
通过ClientHello
和ServerHello
,客户端和服务端就协商好算法套件和用于生成密钥的随机数。
假设客户端和服务端使用默认的TLS_RSA_WITH_AES_128_CBC_SHA
算法,在ServerHello
完成后,服务端必须将本地的RSA证书传给客户端,以便客户端和服务端之间可以进行非对称加密保证对称加密密钥的安全性。
RSA的证书有2个作用:
Client Key Exchange
生成的pre-master key进行公钥加密,保证只有服务端可以解密,确保对称加密密钥的安全性。发送给客户端的是一系列证书,服务端的证书必须排列在第一位,排在后面的证书可以认证前面的证书。
当客户端收到了服务端的ServerHello
时,若客户端也有证书需要服务端验证,则通过该握手请求将客户端的证书发送给服务端,若客户端没有证书,则无需发送证书请求到服务端。
证书必须为X.509v3格式。
使用RSA公钥加密,必须要保证服务端私钥的安全。若私钥泄漏,则使用公钥加密的对称密钥就不再安全。同时RSA是基于大数因式分解。密钥位数必须足够大才能避免密钥被暴力破解。
1999年,RSA-155 (512 bits) 被成功分解。
2009年12月12日,RSA-768 (768 bits)也被成功分解。
在2013年的棱镜门事件中,某个CA机构迫于美国政府压力向其提交了CA的私钥,这就是十分危险的。
相比之下,使用DH算法通过双方在不共享密钥的情况下双方就可以协商出共享密钥,避免了密钥的直接传输。DH算法是基于离散对数,计算相对较慢。而基于椭圆曲线密码(ECC)的DH算法计算速度更快,而且用更小的Key就能达到RSA加密的安全级别。ECC密钥长度为224~225位几乎和RSA2048位具有相同的强度。
ECDH:基于ECC的DH算法。
另外在DH算法下引入动态随机数,可以避免密钥直接传输。同时即使密钥泄漏,也无法解密其他消息,因为双方生成的动态随机数无法得知。
在密码学中该特性被称为前向保密
DHE: 通过引入动态随机数,具有前向保密的DH算法。
ECDHE:通过引入动态随机数,具有前保密的ECDH算法。
当需要TLS双向认证的时候,若服务端需要验证客户端的证书,则向客户端发送Certificate Request
请求获取客户端指定类型的证书。
当服务端处理Hello请求结束时,发送Server Hello Done
消息,然后等待接收客户端握手消息。客户端收到服务端该消息,有必要时需要对服务端的证书进行有效性校验。
当客户端收到了服务端的CertificateRequest
请求时,需要发送Client Certificate
消息,若客户端无法提供证书,则仍要发送此消息,消息内容可以不包含证书。
客户端接收到ServerHelloDone消息后,计算密钥,通过发送Client Key Exchange
消息给服务端。客户端和服务端通过Key Exchange
消息交换密钥,使得双方的主密钥协商达成一致。
以RSA的密钥协商为例。在ClientHello
和ServerHello
分别在客户端和服务端创建了一个32位的随机数。客户端接收到Server Hello Done
消息时,生成最后一个48位的预主密钥。通过服务端提供的证书进行公钥加密,以保证只有服务端的私钥才能解密。
其中预主密钥的前2位要求使用
Client Hello
传输的TLS版本号(存在一些TLS客户端传递的时协商后的TLS版本号,对该版本号检查时可能会造成握手失败)。
需要注意的是,若RSA证书的填空格式不正确,则可能会存在一个漏洞导致客户端发送的PreMasterSecret被中间人解密造成数据加密的对账密钥泄漏。可以看下Attacking RSA-based Sessions in SSL/TLS
若服务端要求客户端发送证书,且客户端发送了非0长度的证书,此时客户端想要证明自己拥有该证书,则需要使用客户端私钥签名一段数据发送给服务端继续验证。该数据为客户端收发的所有握手数据的hash值(不包括本次消息)。
当发送完Change Cipher Spec
消息后必须立即发送该消息。当该消息用于验证密钥交换和身份验证过程是否成功。
Finished
消息是第一个使用协商的算法簇进行加密和防篡改保护的消息。一旦双方都通过了该消息验证,就完成了TLS握手。
VerifyData为客户端收发的所有握手数据的hash值(不包括本次消息)。与Certificate Verify
的hash值可能会不一样。如果发送过Certificate Verify
消息,服务端的握手消息会包含Certificate Verify
握手的数据。
需要注意的是,握手数据不包括协议头的握手协议明文数据(服务端返回
Finished
的验证握手数据是包含接收到客户端的Finished
的明文hash值)。
Finished
消息数据加密和Appilication Data
一致,具体数据加密在Application Data
段进行说明。
改变密码标准协议是为了在密码策略中发出信号转换信号。 该协议由一条消息组成,该消息在当前(不是挂起的)连接状态下进行加密和压缩。 消息由值 1 的单个字节组成。
在接收到该协议后,所有接收到的数据都需要解密。
警报消息传达消息的严重性(警告或致命)和警报的说明。具有致命级别的警报消息会导致立即终止连接。
若在改变密码标准协议前接收到警报消息,是明文传输的,无需解密。
与其他消息一样,警报消息按当前连接状态指定进行加密和压缩。在接收到改变密码标准协议后接收到警报协议,则需要进行解密。解密后即为警报协议明文格式。
加密的Alert消息和加密数据一样,都需要递增加密序号,在数据解密时,递增解密序号。
当客户端和服务端Finished
发送完毕并验证通过后,握手就结束了。后续所有数据都会使用握手协商的对称密钥进行数据加密。
TLS协议实现了数据加密和MAC计算。一般来说有3种加密模式,分别为:
TLS协议使用的是Mac-then-Encrypt
。首先将加密的序号、ContentType、数据长度、数据进计算HMAC-SHA256摘要。然后将摘要拼接到数据后,通过PKCS7格式对摘要+MAC数据进行填充对其和加密块大小一致。最后摘要+MAC+对其填充块
进行加密。
需要注意的是应用程序数据消息有最大长度限制2^14 + 2048
,当超过长度后,数据需要分段传输。每一段都当作单独的数据段进行单独MAC地址并加密。
TLS1.2版本是目前最常用的TLS协议,TLS1.3版本于2018年发表,目前并没有广泛使用。
使用TLS1.2需要注意以下几点:
标签:方法 version sum 扩展性 time 直接 加密算法 历史 填充
原文地址:https://www.cnblogs.com/Jack-Blog/p/13170728.html