1. TLS协议概述
TLS协议包含多个子协议
:
- 应用数据协议(
Application Data Protocol
): 用于密文传输 - 告警协议(
Alert Protocol
):在TLS连接中,如果发生了错误或异常情况,TLS协议会使用Alert Protocol发送警报信息,以通知对方发生了什么问题。 - 握手协议(
Handshake Protocol
):用于密钥协商 - 更改密码规范协议(
Change Cipher Spec Protocol
): 在TLS连接中通知对方加密算法已经切换 - 记录协议(
Record Protocol
): 在TLS连接中对数据进行分段、压缩、加密和认证。上面4个子协议的数据都会通过Record Protocol进行处理,然后再通过网络传输
TLS协议的核心是TLS握手协议
,握手流程如下:
TLS握手过程中客户端和服务端会进行多轮交互
,交互过程中会发送握手协议包
(下文描述中我们称为xx消息
)
上图中标*
的部分根据场景为可选
,如:
- 在
双向认证
中,server发送CertificateRequest
消息, 客户端响应Certificate
消息和CertificateVerify
消息(服务端使用这两个消息验证客户端身份) - 在
会话恢复
(非首次建立TLS链接)中,图中标*
的消息不参与握手流程 - 标
[]
的ChangeCipherSpec
协议不属于握手协议,而是Change Cipher Spec Protocol
子协议
2. 具体案例解析
2.1 总览
上图中抓包结果可以了解到:
(1)通信消息交互使用的TLS版本为TLSv1.2
(2)握手过程中的关键信息有:
- Client Hello- Server Hello- Certificate, Server Key Exchange, Server Hello Done- Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message- New Session Ticket, Change Cipher Spec, Encrypted Handshake Message- Application Data
2.2 SSL/TLS 握手过程详解
2.2.1 客户端 -> 服务端:Client Hello
客户端发送Client Hello Message,表明自己可以使用的SSL版本、以及相应参数。
- client_version:SSL版本。客户端会从高到低去尝试填入自己支持的SSL版本。
- random:客户端随机数。客户端的随机字符序列,用于后续协商密钥。
- session_id:本次会话ID。用于后面恢复会话。如果没有会话ID,则这里可以为空。
- cipher_suites:支持的加密套件列表。根据客户端想要使用的且自己支持的加密套件由高到低排序。
- compression_methods:压缩算法列表。根据客户端想要使用的且自己支持的压缩算法由高到低排序,可以为null,表示不要压缩。
从上图可以看到:
- 握手协议消息类型为
Client Hello
- 客户端支持的TLS版本为
TLS 1.2 (0x0303)
, 其中0x0303
为内部版本号,如TLS1.3为0x0304
- 客户端生成的32字节
随机数
- 客户端支持的
加密套件
,优先级从上到下
2.2.2 服务端 -> 客户端:Server Hello
服务器接受到ClientHello后,会返回ServerHello。服务器从客户端在ClientHello中提供的密码套件、SSL/TLS版本、压缩算法列表里选择它所支持的项,并把它的选择包含在ServerHello中告知客户端,ServerHello中同样会包含一个随机数,同样4+28 字节类型,由服务器生成。
- server_version:服务器支持的SSL版本。例如这里就是SSLv3.0。
- random:服务器随机数。服务器端的随机字符序列,用于后续协商密钥。
- session_id:本次会话ID。如果服务器找到了客户端传过来的session_id会话,并且可以恢复会话,那么这里会填入和Client Hello相同的session_id;否则这里将填入新session_id
- cipher_suite:密钥套件。服务器支持的,且是从客户端给的列表中选的密钥套件。
- compression_method:压缩算法。服务器支持的,且是从客户端给的列表中选的压缩算法。
接下来SSL协议的建立就基于服务器选择的密码套件类型、SSL/TLS协议版本以及压缩算法。
从上图可以看到:
- 握手协议消息类型为
Server Hello
- 服务端确定的TLS版本为
TLS 1.2
- 服务端生成的32字节
随机数
- 服务端确定的
加密套件
为TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
,该加密套件各字段用途如下
2.2.3 服务端 -> 客户端:Certificate, Server Key Exchange, Server Hello Done
【Certificate*】服务器证书
和所选密钥套件中密钥交换算法(Key Exchange)匹配的,用于客户端验证服务器身份和交换密钥的X.509证书。
【Server Key Exchange*】服务器密钥交换信息
如果服务器没有证书,或者服务器的证书仅用来签名(如DSS证书、签名RSA证书),或者使用的是FORTEZZA KEA密钥交换算法(现在已经不用了,不需要去了解),那么就需要发送这条消息。
【Certificate Request *】证书请求
要求客户端也发送它的证书,让服务端校验客户端的身份。
【Server Hello Done】服务器Hello阶段结束信息
一条简单的表明状态的空消息。
从上图可以了解到,本次通信tcp包携带了3个tls握手协议包:
- Certificate消息:Server Key Exchange消息:
- 1.1服务端证书,
id-at-commonName=*.pku.edu.cn"
表示为北京大学服务器网站 - 1.2证书链,该证书链包含根证书
id-at-commonName=DigiCert Global Root CA
, 该根CA为知名签发机构(隶属于美国)
- 1.1服务端证书,
- Server Key Exchange消息:
- 2.1 服务端DH参数,参与生成主密钥
- 2.2 服务端签名,用于验证消息有效性
- Server Hello Done消息:通知客户端加密套件协商结束
2.2.4 客户端 -> 服务端:Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
【校验服务器身份】
客户端会校验服务器发过来的证书的合法性,包括:
- 证书链的可信性
- 证书是否被吊销
- 证书是否处于有效期
- 证书的域名是否和当前访问域名匹配
如果发现证书不合法,客户端可以发起告警信息。
从上图可以了解到,本次通信tcp包携带了3个tls握手协议包:
- Client Key Exchange消息Change Cipher Spec消息:通知服务端,客户端已准备好进行密文通信Change Cipher Spec消息:通知服务端,客户端已准备好进行密文通信
- 1.1 客户端DH参数,参与生成主密钥
- Change Cipher Spec消息:通知服务端,客户端已准备好进行密文通信
- Encrypted Handshake Message消息:同Finished消息(密文形式)
2.2.5 服务端 -> 客户端: New Session Ticket, Change Cipher Spec, Encrypted Handshake Message
【Certificate*】客户端证书
如果服务器发送了“Certificate Request”,要求校验客户端身份,那么客户端需要回应自己的证书。如果客户端没有合适的证书,直接抛出告警信息让服务端处理(服务端的处理方式通常就是断开TCP连接)。和所选密钥套件中密钥交换算法(Key Exchange)匹配的,用于服务器验证客户端身份的X.509证书。
【Client Key Exchange*】客户端密钥交换信息:合法性校验通过后,客户端计算产生随机数字Pre-master,并用证书公钥加密,发送给服务器。
对于不同的密钥交换算法,密钥交换信息格式也不同:
密钥交换算法 |
密钥交换信息 |
---|---|
RSA |
EncryptedPreMasterSecret |
Diffie-Hellman |
ClientDiffieHellmanPublic |
Fortezza Kea |
FortezzaKeys |
通常我们都会用RSA,而RSA的密钥交换信息就是加密的预主密钥(Encrypted Pre-Master Secret)。服务端会生成48字节的预主密钥,用服务器传过来的公钥证书加密该预主密钥。
【Certificate Verify*】客户端证书校验信息
用于提供客户端证书的显示校验信息,仅在具有签名功能的客户端证书(也就是除包含固定diffie-hellman参数的证书外的所有证书)之后发送。它是采用客户端的私钥加密的一段基于已经协商的通信信息得到的数据,服务器可以用公钥解密验证。
【Change Cipher Spec】更换加密规约
此时客户端已经获得全部的计算协商密钥所需信息:两个明文随机数random_S与random_C,还有自己计算产生的Pre-master。
用于提示服务端这条连接以后都使用当前协商好的加密方式以及主密钥,是一条事件消息。
【Finish(Encrypted Handshake Message)】完成信息
当所有操作完成后,发送Finish信息。Finish信息包含了Handshake信息、主密钥的哈希散列(如SHA、MD5)数据,用于验证身份校验和密钥交换过程都成功了。Finish消息不要求收到回包,发送之后可以立刻进行加密应用数据传输。
从上图可以了解到,本次通信tcp包携带了3个tls协议包:
- New Session Ticket消息: 服务器在TLS握手过程中生成一个新的会话票据(Session Ticket),并将其发送给客户端。客户端可以在后续的TLS握手中使用该会话票据来恢复之前的会话状态,从而避免了重新进行完整的TLS握手流程,提高了握手的效率和安全性。
- Change Cipher Spec消息:通知客户端,服务端已准备好进行密文通信
- Encrypted Handshake Message消息:同Finished消息(密文形式)
2.2.6 客户端 <-> 服务端:Application Data
服务端同样地发送Change Cipher Spec、Finish(Encrypted Handshake Message)消息,然后开始数据传输。
从上图可以看到:
- 该消息不属于TLS握手协议,属于
Application Data Protocol
,是TLS协议的另一个子协议。 - Encrypted Application Data: 所有应用数据都被加密传输。
转自:https://www.cnblogs.com/informatics/p/17433116.html,作者为:warm3snow