目录
tls(transport layer security):
ssl和tls简介
ssl/tls是网络安全的基石,广泛应用于互联网上的安全通信,包括https、安全电子邮件、vpn等多种服务。
ssl(secure sockets layer)
ssl协议是为网络通信提供安全性和隐私保护的标准协议,最初由网景公司开发,后来被大部分浏览器和服务器广泛采用。ssl协议经历了以下版本:
ssl 1.0:
- ssl的第一个版本从未公开发布,因为它有着严重的安全漏洞。
ssl 2.0:
- netscape于1995年发布,是ssl协议的第一个正式版本。
- 由于存在诸多严重的安全缺陷,包括弱加密算法、容易受到降级攻击等问题,现已被废弃,不再被任何现代浏览器或服务器支持。
ssl 3.0:
- netscape于1996年发布,是对ssl 2.0的重大改进,这个版本包含了重要的安全改进和增强,例如引入了握手过程的改进,更好地保护了通信双方的隐私。
- 尽管比ssl 2.0更加安全,但随着时间推移,ssl 3.0也被发现存在若干安全隐患,例如poodle攻击,因此也被逐步淘汰。
tls(transport layer security):
1999年,互联网工程任务组(ietf)标准化了ssl的后续版本,并将其命名为tls(transport layer security,传输层安全),旨在提供更为安全和标准化的加密通讯方式。tls 1.0(rfc 2246)被认为是ssl 3.1的升级版,它修复了ssl 3.0中的一些安全问题,并提供了向后兼容性。tls与ssl的主要区别在于它们的安全特性和标准支持。随着tls版本的迭代,每一代tls协议都在强化安全措施、去除已知漏洞,并支持更先进的加密算法和技术。
tls的各个版本及其特点:
tls 1.0(rfc 2246):
- 发布于1999年,基于ssl 3.0开发,但包含了多项增强安全性的修改。
- 随着时间推移,tls 1.0也暴露出一些安全问题,尽管它曾经被广泛应用,但逐渐被淘汰。
tls 1.1(rfc 4346):
- 发布于2006年,解决了tls 1.0中的一些已知的安全问题,如针对cbc模式的攻击。它引入了显式iv以防止某些类型的攻击,并改进了错误报告机制。。
tls 1.2(rfc 5246):
- 发布于2008年,在很长时间内都是最为广泛部署和支持的版本。
- 它引入了sha-256算法,增加了对aead(authenticated encryption with associated data)加密的支持,并且去除了一些不安全的加密算法。
tls 1.3(rfc 8446):
- 发布于2018年,是当前最新的tls版本。
- 主要改进包括大幅减少握手过程,减小了延迟,移除了一些老旧且不安全的加密算法,强制使用前向保密,并且只支持aead加密算法,增强了性能和安全性。
当前,建议使用的版本是tls 1.3,因其提供了最先进的安全性和性能优化。然而tls 1.2仍在许多系统和环境中广泛使用。多数浏览器和服务器都已经支持tls 1.3,并鼓励用户和网站运营者弃用早期版本,以确保网络通信安全。
tls基本原理
tls在tcp/ip中的位置
在tcp/ip模型中没有正式的“安全层”,tls位于应用层和传输层之间。它使用传输层提供的服务来建立一个安全的通道,然后应用层协议通过这个安全通道传输数据。tls协议确保了数据的机密性、完整性和认证。
在实际的数据传输中,tls协议会加密应用层的数据,并将加密后的数据传递给传输层。传输层将这些数据封装在tcp或udp数据包中,并将它们发送到网络层。网络层进一步封装这些数据包并在网络中传输它们。当数据到达目的地时,这个过程会反向进行,最终应用层会接收到通过tls解密后的原始数据。
基本原理
tls协议在客户端和服务器之间建立安全通信时使用数字证书来进行身份验证,不同版本的流程稍有差异,但是基本原理都一样,下面先大致看一下基本原理:
-
客户端发起连接:客户端(例如,web浏览器)向服务器发起一个安全连接请求,通常这是通过在url中使用
https
而不是http
来完成的。 -
服务器提供证书:作为响应,服务器将自己的数字证书(通常包含服务器的公钥)发送给客户端。这个证书由一个信任的证书颁发机构(ca)签发。
-
客户端验证证书:客户端接收到服务器的证书后,进行以下检查:
- 证书的合法性:客户端使用预先安装的信任ca的根证书来验证服务器证书的签名。如果签名有效,表明证书是由信任的ca颁发的。
- 证书的有效期:客户端检查证书的有效日期,确保证书在有效期内。
- 证书的撤销状态:客户端可能会检查该证书是否已被吊销,这可以通过访问ca的证书吊销列表(crl)或使用在线证书状态协议(ocsp)完成。
- 服务器的身份:客户端验证证书中的“subject name”或“subject alternative name”字段是否与请求的服务器域名匹配。
- 其他扩展:客户端还可以检查证书的其他扩展,如“basic constraints”、“key usage”等,以确保证书的用途符合预期。
-
密钥交换:如果证书验证成功,客户端使用证书中的公钥对一个生成的随机密钥(预主密钥)进行加密,并将其发送给服务器。服务器使用自己的私钥解密这个预主密钥。
-
建立加密会话:客户端和服务器使用预主密钥生成会话密钥,并使用这个密钥对接下来的通信进行加密。
-
通信:一旦安全通道建立,客户端和服务器就可以开始加密的通信了。
tlsv1.3
key_share
在tls 1.3中,key_share
是握手过程中的一个重要扩展,它用于在客户端和服务器之间进行密钥交换。这个字段的引入是为了支持elliptic curve diffie-hellman (ecdhe) 或 finite field diffie-hellman (dhe) 密钥交换算法。这允许tls 1.3在只需一次完整的往返通信(1-rtt)的情况下完成握手,从而减少了握手延迟并提高了性能。
key_share
扩展的格式如下:
struct {
keyshareentry client_shares<0..2^16-1>;
} keyshareclienthello;
struct {
keyshareentry server_share;
} keyshareserverhello;
struct {
namedgroup selected_group;
} keysharehelloretryrequest;
keyshareentry
keyshareentry
是一个结构体,它包含了两个字段:group
和key_exchange
。
group
- 这个字段指定了密钥交换使用的命名组。命名组是预定义的,它确定了使用的加密算法,比如特定的椭圆曲线或有限域(finite field)。
key_exchange
key_exchange
字段包含密钥交换的具体信息。这部分内容取决于选定的group
以及相应的定义。这个字段的内容是二进制的,并且其格式和解释取决于所使用的命名组的类型。比如,对于椭圆曲线组,key_exchange
将包含ecdhe的公钥。
keyshareclienthello
在clienthello
消息中,key_share
扩展的extension_data
字段包含一个keyshareclienthello
值。这个结构体包含一个client_shares
向量,它是客户端提供的keyshareentry
值的列表,按客户端偏好的降序排列。
client_shares
这是客户端提供的密钥共享条目的列表,按照客户端的偏好顺序排列。
客户端提供的keyshareentry:
客户端可以提供多个keyshareentry
值,每个值代表一组支持的密钥交换参数。客户端不应该为同一个组提供多个keyshareentry
值,也不应该为其supported_groups
扩展中未列出的组提供任何keyshareentry
值。服务器可以检查这些规则是否被违反,并且如果违反,可以使用"illegal_parameter"警报中止握手。
helloretryrequest
如果服务器需要客户端使用特定的密钥交换组重试clienthello
,则它会发送一个helloretryrequest
消息。在这条消息中,key_share
扩展的extension_data
字段包含一个keysharehelloretryrequest
值。
selected_group
服务器选择的支持的组,要求客户端为此组重试clienthello
和keyshare
。
客户端对helloretryrequest的响应
客户端必须验证收到的helloretryrequest
中的selected_group
字段
- 是否对应于原始
clienthello
中提供的supported_groups
扩展中的一个组 - 不对应于原始
clienthello
中的key_share
扩展提供的一个组
如果以上两点任何检查失败,客户端必须使用"illegal_parameter"警报中止握手。否则,在发送新的clienthello
时,客户端必须只包含selected_group
字段中指示的组的一个新的keyshareentry
。
keyshareserverhello
在serverhello
消息中,key_share
扩展的extension_data
字段包含一个keyshareserverhello
值。
server_share
服务器提供的一个keyshareentry
值,它必须和客户端的共享中的一个相同的组。
使用(ecdhe)的服务器提供的keyshareentry
如果使用(ecdhe)密钥建立,服务器在serverhello
中提供一个keyshareentry
。这个值必须与客户端提供的服务器选择的keyshareentry
值在同一个组中。服务器不得为客户端的supported_groups
扩展中未指示的任何组发送keyshareentry
,并且在使用"psk_ke"密钥交换模式时不得发送keyshareentry
。
如果客户端收到了包含key_share
扩展的helloretryrequest
,并且使用(ecdhe)密钥建立,那么客户端必须验证serverhello
中选定的namedgroup
是否与helloretryrequest
中的相同。如果这个检查失败,客户端必须使用"illegal_parameter"警报中止握手。
流程
基本流程如下:
- 客户端发送clienthello消息:
- 客户端开始tls握手,发送clienthello消息给服务器。这个消息包括客户端支持的tls版本、提供的密码套件列表、随机数(client random)、可能的
key_share
(用于密钥交换的公钥材料)、supported_groups
(支持的密钥交换组)、signature_algorithms
(签名算法)和其他tls扩展。
- 客户端开始tls握手,发送clienthello消息给服务器。这个消息包括客户端支持的tls版本、提供的密码套件列表、随机数(client random)、可能的
- 服务器响应serverhello消息:
- 服务器接收到clienthello后,选择一个共同支持的tls版本和密码套件,生成自己的随机数(server random),并发送serverhello消息回客户端。这个消息还包括服务器的
key_share
扩展和其他选择的参数。
- 服务器接收到clienthello后,选择一个共同支持的tls版本和密码套件,生成自己的随机数(server random),并发送serverhello消息回客户端。这个消息还包括服务器的
- 服务器发送加密证书:
- 服务器发送其数字证书,以便客户端验证服务器的身份。这包括certificate消息和certificateverify消息。certificateverify消息包含服务器证书的签名,证实服务器拥有证书的私钥。
- 服务器发送finished消息:
- 服务器发送finished消息,这是握手消息的加密摘要,用于验证至此为止的握手过程没有受到篡改。
- 客户端验证服务器证书和finished消息:
- 客户端验证服务器的证书链和certificateverify消息中的签名。客户端还会验证服务器的finished消息,确保握手过程的完整性。
- 客户端发送加密证书(如果需要):
- 如果服务器请求客户端认证,客户端将发送certificate和certificateverify消息,类似于服务器发送的消息。
- 客户端发送finished消息:
- 客户端发送自己的finished消息,服务器会验证这个消息,确保握手过程的完整性。
- 应用数据传输:
- 一旦客户端和服务器都验证了对方的finished消息,tls握手就完成了。客户端和服务器现在可以开始安全地传输应用数据。
流程如下图所示:
抓包如下
clienthello
serverhello
certificate
finished
发表评论