详述 TLS 握手流程
握手协议使用若干个报文,它们为服务器认证客户端,为客户端认证服务器,协商加密和散列算法,生成用于数据交换的密码的密钥。握手流程分为两种情况,一种是初始建立会话的完全握手流程,另一种是重用会话的简单流程。
1、完全握手流程
TLS 客户端与服务器之间完成握手协议,实现安全连接,需要 4 个阶段。
*表示可选或视情而定
(1)第一阶段:客户端与服务器之间建立安全增强能力
客户端发送一个 ClientHello 报文,然后等待服务器的响应,服务器必须响应一个 ServerHello 报文,否则将会导致一个致命错误,连接将失败。ClientHello 和 ServerHello 报文用于客户端与服务器之间建立安全增强能力,生成安全参数。
ClientHello 和 ServerHello 建立的属性包括协议版本、会话(Session ID)、密码组和压缩方法。客户端提交的 ClientHello 所包含的密码组(Cipher Suite)是客户支持的密码算法列表(按优先级降序排列),压缩方法是客户支持的压缩方法列表。服务器发送 ServerHello 时,协议版本是客户建议的低版本以及服务器支持的最高版本,密码组是从客户端建议的密码算法中选定的一种算法,压缩方法是从客户支持的压缩方法中选择的一种算法。
ClientHello 和 ServerHello 还要产生和交换两个随机数:ClientHello.random 和 ServerHello.random。随机数是 32 位时间戳加上 28 字节随机序列。
(2)第二阶段:服务器认证
发送 ServerHello 报文之后,服务器需要对自己认证,服务器可以发送它的证书和公钥,也可以请求客户端的证书。具体有以下几种情况。
如果自己要被认证的话,服务器发送自己的证书(Certificate)。Certificate 报文包含一个 X.509 证书,或者一条证书链。除了匿名 DH 之外的密钥交换方法都需要发送 Certificate 报文。
服务器发送 ServerKeyExchange(服务器密钥交换)报文(如果要求这样做)。例如,服务器没有自己的证书,或者证书仅用于签名。ServerKeyExchange 报文包含签名,被签名的内容包括两个随机数以及服务器参数。
非匿名服务器可以向客户端发送 CertificateRequest 报文请求一个客户端证书,该报文包含整数类型和 CA。服务器已被认证,如果对所选的密码组是合适的,它也可能要求客户端发送客户端证书。
服务器发送 ServerHelloDone 报文,指示握手的 Hello 阶段完成,然后等待客户端应答。
(3)第三阶段:客户端认证与密钥交换
客户端收到 ServerHelloDone 报文后,根据需要检查服务器提供的证书,并判断 ServerHelloDone 的参数是否可以接受,如果都没有问题,发送一个或多个报文给服务器。
如果服务器请求证书,则客户端必须首先发送一个 Certificate 报文。但是客户端实在没有证书,就发送一个 No certificate 警告消息。
客户端接着发送 ClientKeyExchange(客户端密钥交换)报文,其内容取决于 ClientHello 和 ServerHello 之间协商选择的公钥算法。
如果客户端发送了一个具有签名能力的证书,还应发送一个 CertificateVerify 报文以显式验证该证书。此报文包含一个签名,对从第 1 条报文以来的所有握手报文的 HMAC 值用主密钥进行签名。HMAC 是 Hash-based Message Authentication Code 的简称,是一种与密钥相关的散列计算消息认证码。HMAC 运算利用散列算法,以一个密钥和一个报文作为输入,生成一个报文摘要作为输出。
(4)第四阶段:建立密码规约
最后客户端和服务器发送报文建立密码规约,允许它们使用这些密钥和参数。
客户端发送一个 ChangeCipherSpec(改变密码规约)报文,将挂起的密码规约复制到当前的密码规约中。紧接着客户端立即用新的算法、密钥和密文加密发送一个 Finished(已完成)报文,这个报文可以检查密钥交换和认证过程是否已经成功,其中包括一个校验值,对所有握手以来的报文进行校验。
作为回应,服务器同样发送 ChangeCipherSpec 和 Finished 报文。服务器发送自己的 ChangeCipherSpec,将挂起的密码规约改为当前密码规约,发送使用新的密码规约的 Finished 报文。
至此,握手过程完成,客户端和服务器可以开始交换应用数据(Application Data)。
2、简单握手流程
客户端和服务器决定重建以前的会话或者复制一个已经存在的会话(而不是重新协商新安全参数),也就是重用已有的 TLS 会话,握手流程就简化了。
与上述完全握手相比,简单握手省略了第二、三两个阶段。
客户端使用含有要重用的会话的会话 ID 参数发送 ClientHello 报文。服务器随后检查是否匹配其会话缓存。如果发现匹配,而且服务器希望在指定的会话状态下重建连接,将发送含有同一会话 ID 的 ServerHello 报文。如果服务器没有发现匹配的会话 ID,将产生一个新的会话 ID,客户端和服务器将开始一个完全的 TLS 握手过程。
紧接着客户端和服务器都必须发送 ChangeCipherSpec(改变密码规约)报文,并直接发送 Finished 报文。
一旦重建会话完成,客户端和服务器就可以交换应用数据。
版权声明: 本文为 InfoQ 作者【穿过生命散发芬芳】的原创文章。
原文链接:【http://xie.infoq.cn/article/42b14a01220e8e0b244d184d0】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论