TLS1.3系列文章(5):TLS1.3握手之认证阶段(2)

581 阅读5分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

8月份更文挑战主题:TLS1.3协议
TLS.png
TLS1.3系列文章(5):TLS1.3握手之认证阶段(2)

2.3.2 CertificateVerify消息

该消息用于明确证明一个端点拥有与其证书相对应的私钥。CertificateVerify消息也为截至当前的握手提供完整性。服务器在通过证书进行验证时必须发送此消息,客户端在通过证书进行验证时必须发送此消息(如Certificate消息非空时)。该消息必须紧接在Certificate消息之后发送,并在Finished消息之前出现。

证书确认载荷消息结果为:

certVerify.png

image-20220724103520128.png

算法字段指定所使用的签字算法。 签名是使用该算法的数字签名。签名计算方式如下:

               Transcript-Hash(Handshake Context, Certificate)

然后,数字签名的计算是在下列各项的连接上进行的

  • 一个由8进制的32(0x20)组成的字符串,重复64次
  • 握手上下文字符串
  • 一个字节的0值,作为分隔符
  • 需要签署的内容

这个结构的目的是为了防止对以前版本的TLS的攻击,在这种情况下,ServerKeyExchange格式意味着攻击者可以获得一个带有32字节前缀(ClientHello.random)的消息签名。 初始的64字节填充会清除这个前缀和服务器控制的ServerHello.random。

服务器签名的context字符串是"TLS 1.3, server CertificateVerify"

客户端签名的context字符串是” TLS 1.3, client CertificateVerify "

它用来区分不同环境下的签名,有助于防止潜在的跨协议攻击。

例如,如果transcript哈希是32字节的01(这个长度对于SHA-256来说是有意义的),那么服务器CertificateVerify的数字签名所覆盖的内容就是:

verifyDemo.png 在发送方,计算CertificateVerify消息的签名字段的输入为

  • 数字签名所涵盖的内容
  • 之前信息中发送的证书所对应的私人签名密钥。

如果CertificateVerify消息是由服务器发送的,签名算法必须是客户端 signature_algorithms扩展中提供的算法,除非没有不支持的算法就不能产生有效的证书链。如果是客户端发送的,签名中使用的签名算法必须是CertificateRequest消息中 signature_algorithms 扩展中supported_signature_algorithms字段中的算法之一。

此外,签名算法必须与发送者的终端实体证书中的秘钥兼容。RSA签名必须使用RSASSA-PSS算法,不管RSASSA-PKCS1-v1_5算法是否出现在signature_algorithms中。 SHA-1算法不得用于任何CertificateVerify消息的签名中。 TLS1.3规范中的所有 SHA-1 签名算法只用于传统证书,而不适用于CertificateVerify签名。

CertificateVerify消息的接收方必须验证签名字段。 验证过程的输入是:

  • 数字签名所涵盖的内容
  • 相关Certificate信息中找到的终端实体证书中包含的公钥。
  • CertificateVerify消息的签名中收到的数字签名。

如果验证失败,接收方必须用decrypt_error警报终止握手。

2.3.3 Finished消息

Finished消息是Authentication阶段中的最后一条消息,它对提供握手和密钥的认证至关重要。Finished消息的接收者必须验证其内容是否正确,如果不正确必须用decrypt_error告警终止连接。

一旦一方发送了Finished消息,并且收到并验证了对端的Finished消息,它就可以开始通过连接发送和接收应用数据。 有两种设置允许它在收到对端的Finished之前发送数据:

  • 发送0-RTT数据的客户端。
  • 服务器在第一次发送后可以发送数据,但由于握手还没有完成,所以既不能保证对端的身份,也不能保证它的活性(如ClientHello可能已经被重放)。

用于计算Finished消息的密钥计算方式如下:

2.3.3 Finished消息

Finished消息是Authentication阶段中的最后一条消息,它对提供握手和密钥的认证至关重要。Finished消息的接收者必须验证其内容是否正确,如果不正确必须用decrypt_error告警终止连接。

一旦一方发送了Finished消息,并且收到并验证了对端的Finished消息,它就可以开始通过连接发送和接收应用数据。 有两种设置允许它在收到对端的Finished之前发送数据:

  • 发送0-RTT数据的客户端。
  • 服务器在第一次发送后可以发送数据,但由于握手还没有完成,所以既不能保证对端的身份,也不能保证它的活性(如ClientHello可能已经被重放)。

用于计算Finished消息的密钥计算方式如下:

finished.png

HMAC[RFC2104]采用Hash算法进行握手。如上所述,HMAC的输入一般可以通过运行哈希来实现,如此时只需要握手哈希。在以前的TLS版本中,verify_data总是12个八位字节长。在TLS 1.3中,是用于握手的Hash的HMAC输出大小。 注意:告警信息和任何其他非握手类型不属于握手消息,不包括在哈希计算中。在Finished消息之后的任何记录必须使用流量密钥进行加密。主要注意的是,它也包括服务器响应客户端Certificate和CertificateVerify消息而发送的任何告警消息