TLS协议中的握手协议

TLS 握手协议(handshake protocol)

握手是TLS协议中最精密复杂的部分。在这个过程中,通信双方协商连接参数(沟通双方各有什么加密算法,选择一个最合适的算法),并且完成身份验证。根据使用的功能的不同,整个过程通常需要交换6~10次信息。根据配置和支持的协议扩展的不同,交换过程可能有许多变种。在使用中经常可以观察到以下三种流程:

(一) 完整的握手,对服务器进行身份验证;

(二) 短握手(恢复以前某个会话 根据session id);

(三) 对客户端和服务器都进行身份验证的握手。

握手协议消息的标头信息包含消息类型(1字节)和长度(3字节),余下的信息则取决于消息类型。

一个系统介绍TLS协议,加密算法,以及使用 openssl 建立私有CA的课程:http://edu.51cto.com/sd/89f15

(一) 完整的握手

TLS连接都会以握手开始。如果客户端此前并未与服务器建立会话,那么双方会执行一次完整的握手流程来协商TLS会话。握手过程中,客户端和服务器将进行以下四个主要步骤。

(1) 交换各自所支持的加密算法(密钥套件),如果需要其他参数,参数也要达成一致。

(2) 验证对方的证书,或使用其他方式进行身份验证。

(3) 对主密钥达成一致。

(4) 验证握手消息的完整性(看是否被第三方修改)。

在实际使用中,第2步和第3步都是密钥交换(更通用的说法是密钥生成)的一部分,如果没有身份验证,主动攻击者就可以将自身嵌入会话,并冒充会话的另一端。

一个TLS握手需要2个RTT (round trip time),一个RTT通俗的说就是一个来回,一来一往就是一个RTT。红色部分是服务器端发送的数据,黑色是客户端。

(1) 客户端开始新的握手( ClientHello),将自身支持的加密功能(Cipher Suites)提交给服务器。

(2) 服务器( ServerHello),选择Cipher Suite。

(3) 服务器发送其证书(Certificate)(当需要服务器身份验证时)。

(4) 根据选择的密钥交换方式,服务器发送生成主密钥的额外信息。

(5) 服务器通知客户端自己完成了协商过程。

(6) 客户端发送生成主密钥所需的额外信息(ClientKeyExchange)。

(7) 客户端切换到加密方式并通知服务器。

(8) 客户端计算发送和接收到的握手消息的MAC并发送。

(9) 服务器切换加密方式并通知客户端。

(10) 服务器计算发送和接收到的握手消息的MAC并发送。

我们逐一讲解每个步骤:

1. ClientHello

在一次新的握手流程中, ClientHello 消息总是第一条消息。这条消息将客户端的功能和首选项传送给服务器。客户端会在新建连接后,希望重新协商或者响应服务器发起的重新协商请求(由 HelloRequest 消息指示)时,发送这条消息。在握手时,客户端和服务器都会提供随机数。这种随机性对每次握手都是独一无二的,在身份验证中起着举足轻重的作用。它可以防止重放攻击,并确认初始数据交换的完整性。

传输的数据:

Handshake protocol: ClientHello

Version: TLS 1.2

Random

Client time: May 22, 2030 02:43:46 GMT

Random bytes: b76b0e61829557eb4c611adfd2d36eb232dc1332fe29802e321ee871

Session ID: (empty)

Cipher Suites

Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256

Suite: TLS_RSA_WITH_AES_128_GCM_SHA256

Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA

Suite: TLS_RSA_WITH_AES_128_CBC_SHA

Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA

Suite: TLS_RSA_WITH_RC4_128_SHA

Compression methods

Method: null

Extensions

Extension: server_name

Hostname: www.feistyduck.com

Extension: renegotiation_info

Extension: elliptic_curves

Named curve: secp256r1

Named curve: secp384r1

Extension: signature_algorithms

Algorithm: sha1/rsa

Algorithm: sha256/rsa

Algorithm: sha1/ecdsa

Algorithm: sha256/ecdsa

 

2. ServerHello

ServerHello 消息的意义是将服务器选择的连接参数传送回客户端。这个消息的结构与ClientHello 类似,只是每个字段只包含一个选项。

Handshake protocol: ServerHello

Version: TLS 1.2

Random

Server time: Mar 10, 2059 02:35:57 GMT

Random bytes: 8469b09b480c1978182ce1b59290487609f41132312ca22aacaf5012

Session ID: 4cae75c91cf5adf55f93c9fb5dd36d19903b1182029af3d527b7a42ef1c32c80

Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

Compression method: null

Extensions

Extension: server_name

Extension: renegotiation_info

服务器无需支持客户端支持的最佳版本。如果服务器不支持与客户端相同的版本,可以提供某个其他版本,只要这个版本客户端也支持。

 

3. Certificate

典型的 Certificate 消息用于携带服务器X.509证书链。证书链是以ASN.1 DER编码的一系列证书,一个接着一个组合而成。主证书必须第一个发送,中间证书按照正确的顺序跟在主证书之后。根证书可以并且应该省略掉,因为在这个场景中它没有用处。

服务器必须保证它发送的证书与选择的算法套件一致。比方说,公钥算法与套件中使用的必须匹配。除此以外,一些密钥交换算法依赖嵌入证书的特定数据,而且要求证书必须以客户端支持的算法签名。所有这些都表明服务器需要配置多个证书(每个证书可能会配备不同的证书链)。

Certificate 消息是可选的,因为并非所有套件都使用身份验证,也并非所有身份验证方法都需要证书。更进一步说,虽然消息默认使用X.509证书,但是也可以携带其他形式的标志;一些套件就依赖PGP密钥。

4. ServerKeyExchange

ServerKeyExchange 消息的目的是携带密钥交换的额外数据。消息内容对于不同的协商算法套件都会存在差异。在某些场景中,服务器不需要发送任何内容,这意味着在这些场景中根本不会发送 ServerKeyExchange 消息。

5. ServerHelloDone

ServerHelloDone 消息表明服务器已经将所有预计的握手消息发送完毕。在此之后,服务器会等待客户端发送消息。

6. ClientKeyExchange

ClientKeyExchange 消息携带客户端为密钥交换提供的所有信息。这个消息受协商的密码套件的影响,内容随着不同的协商密码套件而不同。

7. ChangeCipherSpec

ChangeCipherSpec 消息表明发送端已取得用以生成连接参数的足够信息,已生成加密密钥,并且将切换到加密模式。客户端和服务器在条件成熟时都会发送这个消息。

 

8. Finished

Finished 消息意味着握手已经完成。消息内容将加密,以便双方可以安全地交换验证整个握手完整性所需的数据。这个消息包含 verify_data 字段,它的值是握手过程中所有消息的散列值。这些消息在连接两端都按照各自所见的顺序排列,并以协商新得到的主密钥计算散列。这个过程是通过一个伪随机函数(pseudorandom function,PRF)来完成的,这个函数可以生成任意数量的伪随机数据。

我将在本章的后续部分中对其进行介绍。散列函数与PRF一致,除非协商的套件指定使用其他算法。两端的计算方法一致,但会使用不同的标签:客户端使用client finished,而服务器则使用serverfinished。verify_data = PRF(master_secret, finished_label, Hash(handshake_messages))因为 Finished 消息是加密的,并且它们的完整性由协商MAC算法保证,所以主动网络攻击者不能改变握手消息并对 vertify_data 的值造假。

理论上攻击者也可以尝试找到一组伪造的握手消息,得到的值与真正消息计算出的verity_data 的值完全一致。这种攻击本身就非常不容易,而且因为散列中混入了主密钥(攻击者不知道主密钥),所以攻击者根本不会尝试。

在TLS 1.2版本中, Finished 消息的长度默认是12字节(96位),并且允许密码套件使用更长的长度。在此之前的版本,除了SSL 3使用36字节的定长消息,其他版本都使用12字节的定长消息。

 

(二) 短握手

完整的握手需要发送多次信息,是一个耗时的操作。服务器为会话指定唯一会话ID。服务器在ServerHello 消息中将会话ID发给客户端。希望恢复之前会话的客户端将会话ID放入 ClientHello 消息。服务器如果愿意恢复会话,就将相同的会话ID放入 ServerHello 消息返回,切换到加密模式,发送 Finished 消息。

 

(1) 客户端恢复握手( ClientHello),session id

(2) 服务器ServerHello , session id

(3) 服务器切换加密方式并通知客户端。

(4) 服务器计算之前发送和接收到的所有有关握手的消息,形成MAC并发送(签名)

(5) 客户端切换到加密方式并通知服务器。

(6) 客户端计算发送和接收到的握手消息的MAC并发送。

 

(三) 对客户端和服务器都进行身份验证的握手

服务器发送 CertificateRequest 消息请求对客户端进行身份验证。客户端发送自己的 Certificate 消息(使用与服务器发送证书相同的格式),并附上证书。此后,客户端发送 CertificateVerify 消息,证明自己拥有对应的私钥。其中的5,7,9三个步骤是比普通的完整握手多出来的。

 

(1) 客户端开始新的握手( ClientHello),将自身支持的加密功能(Cipher Suites)提交给服务器。

(2) 服务器选择Cipher Suite。

(3) 服务器发送其证书(当需要服务器身份验证时)。

(4) 根据选择的密钥交换方式,服务器发送生成主密钥的额外信息。

(5) 服务器发送 CertificateRequest

(6) 服务器通知自己完成了协商过程。

(7)客户端发送自己的 Certificate

(8) 客户端发送生成主密钥所需的额外信息。

(9) 客户端发送 CertificateVerify 消息,证明自己拥有对应的私钥

(10) 客户端切换到加密方式并通知服务器。

(11) 客户端计算发送和接收到的握手消息的MAC并发送。

(12) 服务器切换加密方式并通知客户端。

(13) 服务器计算发送和接收到的握手消息的MAC并发送

 

 

 

 

你可能感兴趣的:(TLS/SSL协议)