TLS/SSL 协议详解 (9) Client hello


TLS/SSL 协议详解 (9) Client hello_第1张图片

  SSL报文格式可以大致分为2部分,Record层 和 Handshake层,Record层中指定了后续数据的类型,SSL版本(一般来说固定),以及后续数据的长度。Handshake层欧威Record层的负载,其关系类似TCP层的数据作为IP层的负载。

例如上图中显示的那样,SSL报文头部是TVL格式:

  Content Type: Handshake

  Version: TLS 1.0

  Length: 121

  这些表示后续的Handshake层是握手报文,TLS1.0格式,总长度是121字节。

Handshake层,又有自己的格式,根据不同的类型,比如Client HelloCertificate,等,有自己的格式(所以Record中的Content Type字段是必要的),并且不同的版本之间也有不同的格式,例如TLS1.0SSL 3.0Client key exchange报文有自己的组织方式(所以Record中的Version字段也是必要的)。长度字段有效的确定了单个SSL报文结束的位置,因为SSL报文承载与TCP之上,一个TCP段中存在多个SSL报文是非常常见的事情,如果没有字段描述单个SSL报文的长度,那么解析报文将变得不可能。


(1)Random

  随机数,一共32字节,其中前4个字节使用系统当前时间,后28字节使用伪随机函数生成的随机数。4个字节以Unix时间格式记录了客户端的协调世界时间(UTC)。协调世界时间是从197011日开始到当前时刻所经历的秒数,那么时间是不断的上涨的,通过前4字节填写时间方式,有效的避免了周期性的出现一样的随机数。使得“随机”更加“随机”。随机数用来干什么?随机数是用来生成对称密钥的,我们后续讲到生成对称密钥的时候,会再次提到随机数。现在只需要记住“客户端生成了一个随机数,然后发送到的服务器”。

 然而在具体的实现上,不同客户端行为不一样,IE会带时间,而Firefox就不带时间,因为它本身的含义就是随机数,而对端也不会校验这个时间(和tcp的时间戳完全不是一回事儿)。

 随机数参与了SSL握手的 master key的计算、KDF计算、server_key_exchange的签名值的计算。属于混淆的一部分。


(2)Session id

  标识了后面Session id的长度,但是对于一般新建的会话,Session id length都是0,如果Session id length有值,对于 SSL 2.0 Session id length0~16字节,其后的版本扩大到32字节。本报文中Session id length0,后面就没有跟Session id,直接是Cipher suit length。下面是Session id不是0的报文:



一眼就能看出差别了把!Session id在会话复用中被用到,我们讲到会话复用的时候,会提及Session id,本章分析报文时,不会再提及Session id

Session id并不一定是32字节,RFC规定可以0~32字节。只是Session id由服务器生成,服务器普遍采用OpenSSL,而OpenSSL基本只生成32字节的session id,如果碰到其他字节长度的Session id,切莫认为是异常client hello



(3)Cipher Suite



Cipher Suits Length:含义同Session id length

Cipher Suits:加密套件,它列出了客户端能够支持的加密方式、算法等信息。不同的加密套件性能不一样,安全性不一样,也导致了SSL交互报文的不一样。

  最常见的如TLS_RSA_WITH_RC4_128_SHA1,它表示我们密钥交换使用RSA,身份认证算法用RSA(咦,怎么和之前说的不一样,身份认证难道不是证书吗?是的,证书是身份认证一部分,我们还需要用RSA去验证证书,后面会讲到),对称加密算法使用RC4,摘要算法使用SHA1。再举个例子,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA1,它表示,密钥交换算法使用ECDHE(短暂椭圆曲线),身份认证算法使用ECDSA,对称加密算法使用AES_128_CBC,摘要算法使用SHA1

  客户端把自己所支持的加密套件全部发送给服务器,服务器会从中选择一个加密套件。这个我们将在后面的Server hello中讲到。

每个加密套件用2字节表示,这里一共12个加密套件,所以理所当然的,Cipher Suits Length12 * 2 = 24字节。


(4)Compression Methods

目前没见过使用压缩算法的实例。这里不再拓展。


(5)Extension


拓展字段的存在,是因为SSL协议起草之初有些功能没有考虑到,后续这些功能被加进RFC,而为了兼容SSL,把这些功能的描述放到Extension中。Extension很大程度上影响了SSL的流程,很多人觉得某些SSL连接的报文好奇怪、和正常接触的SSL报文不一样,就是因为Extension起的作用。

TLS 1.3 就借助 extension 发送不同curve的pubkey来减少RTT,后续有机会再说。这里介绍主流的一些拓展。

1Renegotiation info

如果是重新协商(即加密的hello),那么会带上上次协商的12字节的finished,如果是新hello请求,那么里面字段为0

 切记及时服务器端不支持renegotiation,在server hello响应时也需要带上这个拓展(前提是客户端有这个拓展或者有等价的EMPTY_SCSV,因为我在实现上碰到过如果不带该拓展,导致客户端结束连接的情况)。

 

2Server_name(SNI):

SSL存在验证证书的时候,有这么一个判断:比较“浏览器输入的地址”和“获取的证书的名称”,如果一样,那么接着验证,如果不一样,那么认为证书是不可信的。

假设有公司的域名存在2个:www.123.comwww.567.com,它们对应的ip都是222.12.34.56,假设服务证书的名字是 ”www.123.com”  ,那么从 ”www.567.com” 访问过来的用户无法信任服务器证书,总之,总有一个域名访问会导致客户端无法信任服务器。为了解决这个问题,客户端在client hello中带上server name 拓展(如果使用ip地址进行访问,那么就不会有server name拓展),它会捎带上域名地址,服务器解析到server name后,就会根据server name中的域名,选择合适的证书。

 

3Elliptic_curves/ec_point_formats:

使用椭圆曲线密钥交换算法的时候用到,里面列举了自己支持的椭圆曲线算法,供服务器选择。


4application_layer_negotiation(ALPN):

用以描述支持的上层协议,h2http/1.1spdy等。可以把他想象成IP头中的protocol,描述了上层是TCP还是UDP还是ICMP

 目前主流浏览器,若要使用HTTP2,则必须使用这个拓展。

5status_request

请求OCSP,服务器可以发送cettificate status到客户端,里面带上ocsp的信息。


6signature_algorithms

表示自己支持的签名算法,服务器收到这个拓展,在进行例如server key exchange签名等操作时,需要参考客户端这个拓展。

 

(7)SessionTicket TLS

   Session ticket会话复用时使用,讲到session ticket时再说。


注意,老的一些客户端没有extensions length字段,而新的客户端如果不携带extension,他也会有extensions length,只是为0。所以判断有没有extension 存在的方式是compression methods是否在client hello的最后。



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