SSL和TLS-SSL Handshake Protocol

SSL握手协议位于SSL记录协议之上。它允许客户端和服务器互相认证,协商cipher suites和压缩方法。
The SSL handshake protocol

上图中的方括号里的消息是可选的,不总是被发送。ChangeCipherSpec实际上不是SSL握手协议的消息。SSL握手协议包含四组消息-叫flights-在客户端和服务器之间交换。一个flight的所有消息可以在一个TCP段内传输。也可能包含一个叫做HelloRequest的第五个flight(type值是0x00),它可能从服务器发送给客户端,初始化一个SSL握手。很少使用这个消息。消息必须以这样的顺序发送,否则返回致命错误。

  • ClientHello:从客户端发给服务器(type值是0x01)
  • 第二个flight包含2-5个消息,从服务器发给客户端
    • ServerHello:响应ClientHello消息(type值是0x02)
    • Certificate:如果服务器需要证明自己,就发送(type值是0x0B)
    • ServerKeyExchange:某些情况下,需要发送(type值是0x0C)
    • CertificateRequest:如果服务器需要客户端使用公钥证书证明自己(type值是0x0D)
    • ServerHelloDone:最后发送(type值是0x0E)
      交换完ClientHello和ServerHello,客户端和服务器协商好协议版本、session ID、cipher suite和压缩方法。此外,已经生成了ClientHello.random和ServerHello.random。
  • 第三个flight包含2-5个消息,从客户端发给服务器
    • Certificate:如果服务器发送了CertificateRequest,客户端发送(type值是0x0B)
    • ClientKeyExchange:这是协议的主要步骤。此消息的内容取决于key交换算法(type值是0x10)
    • CertificateVerify:如果客户端发送了Certificate消息,就必须发送CertificateVerify。此消息使用与客户端证书的公钥对应的私钥进行数字签名。(type值是0x0F)
    • ChangeCipherSpec:使用SSL change cipher spec协议发送该消息。它的pending write状态变成current write状态
    • Finished:这是第一个使用cipher spec加密保护的消息(type值是0x14)
  • 最后一个flight包含2个消息,从服务器发给客户端
    • ChangeCipherSpec:
    • Finished:

这样,握手完成了。客户端和服务器开始使用SSL application data protocol交换应用层数据。
大多数SSL session从握手开始,交换一次应用数据,等一会就结束了。如果需要交换更多数据(同一个客户端和服务器之间),有两种可能行:或者是一个全的握手协商一个新的session,或者是一个简单的握手继续一个旧的(先前建立的)session。
SSL协议允许客户端在任何时间简单地发送一个ClientHello消息,请求session重新协商。如果服务器想重新协商,就发送HelloRequest消息。
比如,一个web服务器的大部分文档都可以匿名请求,但是有一部分资源需要基于证书的客户端认证,服务器就可以重新协商一个连接。
如果顺序号太大,也可以重新协商。
客户端发送一个带有session ID的ClientHello消息,服务器就在它的session缓存里查找,如果找到了,服务器就重新建立连接,返回包含该session ID的ServerHello。如果找不到,就需要完整的握手。

The simplied SSL handshake protocol

SSL握手的每一个消息,使用一个字节的type属性开始,3个字节的length属性说明消息的长度。多个握手消息可以放在一个SSL记录里。SSL记录的前五个字节是头。头的第一个字节是22,表示握手协议,下来的两个字节是版本,最后两个字节是整个SSL记录的剩余部分的长度。
The general structure of an SSL handshake protocol message

HelloRequest

该消息允许服务器要求客户端初始化新的SSL握手。一般不用。
HelloRequest

ClientHello

SSL握手的时候,客户端发给服务器的第一个消息。一般,它是SSL握手的开始。它开始于通用的5字节的SSL记录头,type属性是1,3字节的length属性。
它的消息体是:

  • length属性后面是client_version,客户端支持的SSL最高版本
  • 接下来的32个字节是random,客户端生成的随机数,由两部分组成:
    • 4字节的日期+时间值,单位是秒。1970年以来的UTC时间
    • 28个字节的随机数
  • 然后是session ID的长度。如果值是0,表示没有可继续的旧session,或者客户端想生成新的安全参数,服务器选择恰当的session ID。否则,如果session ID长不为0,后面就是ID
  • 如果session ID长度大于0,就有session_id属性。session ID的最大长度是32个字节。注意,此时还不能加密,所以不要在session ID里存放任何信息
  • 下来的2个字节是客户端支持的cipher suites数量。
  • 客户端支持的每个cipher suites使用2个字节表示。SSL里,第一个字节总是0
  • 下来的2个字节是客户端支持的压缩方法的数量
  • 接下来是压缩方法,每个方法有一个唯一的编码。SSL 3.0只定义了null压缩,它的长度是1,接下来的字节是0

为了向前兼容,compression_methods后面可以跟随其他属性。这些数据必须包含在握手hash里,否则被忽略。
ClientHello

ServerHello

收到ClientHello消息,服务器开始处理和验证,返回ServerHello。
ServerHello的结构和ClientHello类似,服务器只返回一个cipher suite和一个压缩方法。服务器只能从客户端的选项中选一个,放到session里使用。

在这里插入图片描述

Certificate

大多数key交换方法都不是匿名的,这意味着服务器必须使用公钥证书向客户端认证自己(除了DH anon)。因此,服务器向客户端发送完ServerHello消息,马上发送Certificate消息(在同一个flight内)。同样,在SSL握手的时候,当服务器发送CertificateRequest消息,客户端就要回复Certificate消息。不论如何,Certificate消息传送公钥证书,或者是公钥证书链(certificate_list)。公钥证书链以发送者的证书开始,然后是一系列的CA证书,向上一直到根CA证书。证书类型必须适合使用的key交换算法。一般是X.509证书。
Certificate

Certificate消息以SSL记录头开始,然后是type属性,3字节的length属性和实际的证书链。
每个证书也以3字节的length开始。Certificate消息可能很长。

ServerKeyExchange

如果使用RSA key交换,客户端可以从服务器证书里检索公钥,以及使用这个公钥加密pre master secret。类似地,如果使用fixed Diffie-Hellman key交换,客户端可以从服务器证书里检索Diffie-Hellman参数。采用这些参数执行Diffie-Hellman key交换,把结果当作pre master secret。
这两种情况下,服务器的Certificate消息足够(不需要附加信息)客户端安全地把re master secret发给服务器。特别是,不需要ServerKeyExchange消息。
其他时候,客户端需要附加信息,必须由服务器发送ServerKeyExchange。
key交换算法不同,ServerKeyExchange消息格式也不一样。
The beginning of an SSL S ERVER K EY E XCHANGE message using Diffie-Hellman

The beginning of an SSL S ERVER K EY E XCHANGE message using RSA

The beginning of an SSL S ERVER K EY E XCHANGE message using FORTEZZA

  • 如果使用ephemeral或者anonymous Diffie-Hellman,ServerKeyExchange消息的剩余部分是素数模p,生成器g和公共指数Ys。这些参数的都是变长的
  • 如果使用RSA,服务器有RSA key的签名,客户端不能使用服务器的公钥发送加密的pre master secret。服务器必须增加一个临时的RSA公钥对,使用ServerKeyExchange消息把公钥发给客户端。消息包含两个参数:模和指数。这些参数必须经过数字签名。参数也是变长的
  • 如果使用FORTEZZA,ServerKeyExchange消息只包含FORTEZZA KEA需要的服务器的rs,长度是128字节。不需要数字签名

前两种情况,ServerKeyExchange可以包含签名部分。如果服务器认证不是SSL session的一部分,就不需要签名部分,ServerKeyExchange消息以Diffie-Hellman参数或者RSA参数结束。如果服务器不是匿名的,已经发送了Certificate消息,签名的参数格式依赖服务器证书里的签名算法(RSA或者DSA)

  • 如果服务器证书使用RSA签名,签名的参数由两个hash值连接而成:一个MD5 hash值和一个SHA-1 hash值
  • 如果使用DSA签名,签名的参数只有SHA-1 hash值

hash函数的输入是ClientHello.random、ServerHello.random和上面提到的服务器key参数。

CertificateRequest

非匿名的服务器可以要求客户端认证。这个消息不只是要求客户端发送证书,还包括客户端证书类型的信息。
CertificateRequest消息包含可接受的证书类型列表,还包含服务器可接受的CA列表。
该消息可能很长。
An SSL C ERTIFICATE R EQUEST message

ServerHelloDone

消息体为空。
An SSL S ERVER H ELLO D ONE message

ClientKeyExchange

客户端发送的消息。提供了客户端侧加密材料,让服务器在后来的安全通信中使用。消息体和使用的key交换算法相关。

An SSL C LIENT K EY E XCHANGE message using RSA

An SSL C LIENT K EY E XCHANGE message using FORTEZZA

An SSL C LIENT K EY E XCHANGE message using Diffie-Hellman

  • 如果使用RSA或者FORTEZZA,ClientKeyExchange消息包含加密的48个字节的pre_master_secret。前两个字节是客户端支持的最新版本。服务器应该检查这个值和ClientHello里的值
    • 对于RSA,pre_master_secret使用服务器的RSA公钥或者ServerKeyExchange里的临时RSA key
    • 对于FORTEZZA,使用KEA派生TEK,使用TEK加密pre_master_secret和其他加密参数。FORTEZZA key材料实际上由10个值组成
  • 如果使用ephemeral或者anonymous Diffie-Hellman,消息包含客户端的公开的Diffie-Hellman参数Yc。如果是fixed Diffie-Hellman,客户端的公开的Diffie-Hellman参数已经在Certificate消息里了,不需要ClientKeyExchange。

如果服务器收到ClientKeyExchange消息,它使用私钥解密pre_master_secret,或者使用自己的Diffie-Hellman参数计算pre_master_secret。

CertificateVerify

如果客户端提供的Certificate消息里有带签名的证书,它必须证明自己拥有相应的私钥(证书不能证明客户端的身份,因为证书可以被窃听和重播)。客户端发送CertificateVerify消息,该消息包含的数字签名由客户端的私钥生成。

  • 如果客户端的证书是RSA的,包含MD5 hash值和SHA-1 hash值
  • 如果证书是DSA的,只有SHA-1 hash值

hash值是这样计算的:
h(k || opad || h(handshake messages || k || ipad))

h是指MD5或者SHA-1,k是master secret。
CertificateVerify

Finished

Finished消息总是在ChangeCipherSpec消息之后马上发送。该消息用来验证key交换和认证过程胜利结束。它是使用新的协商算法和key保护的第一个消息。不需要确认,之后可以立刻发送加密数据。
Finished消息的消息体是加密保护的,由type、length、16字节的MD5 哈是值、20字节的SHA-1 hash值,16或者20字节的MAC。MD5和SHA-1 hash值依赖key和实际的MAC。这里的MAC和SSL记录里计算的MAC不同,附加在消息里。
MD5和hash值这样计算:
h(k || opad || h(handshake messages || sender || k || ipad))

其中,sender是发送消息的实体。如果是客户端发送的,值是0x434C4E54,否则是0x53525652。

Finished

猜你喜欢

转载自blog.csdn.net/weixin_43364172/article/details/83859867