1

TLS中ChangeCipherSpec为什么是个单独的协议类型

 1 year ago
source link: http://suntus.github.io/2020/03/14/TLS%E4%B8%ADChangeCipherSpec%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E4%B8%AA%E5%8D%95%E7%8B%AC%E7%9A%84%E5%8D%8F%E8%AE%AE%E7%B1%BB%E5%9E%8B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

TLS中ChangeCipherSpec为什么是个单独的协议类型

发表于

2020-03-14 22:27

|

更新于 2021-04-29 17:15

RFC5246中说:

Note: To help avoid pipeline stalls, ChangeCipherSpec is an independent TLS Protocol content type, and is not actually a TLS handshake message.

为了避免pipeline stall,ChangeCipherSpec是个单独的协议类型,不属于握手协议。这里什么是pipeline stall?

1. pipeline stall

通俗点的理解是,在CPU流水线设计中,有些指令必须在某些指令之后执行,中间需要停顿一下,等待前一个指令执行完,才能开始后一个指令;或者逻辑分支时,需要控制程序指令转移,导致流水线停顿。如果这样的stall过多,就会影响的性能。可以采取一些办法减少或避免停顿。

2. TLS1.2及之前的ChangeCipherSpec

为什么ChangeCipherSpec需要是单独的类型呢?如果是握手协议类型,TLS协议规定相同协议类型的数据可以集中到一个record中发送,也就是说,一个record中可以同时存放ClientKeyExchange,ChangeCipherSpec,Finished这三个消息,其中ClientKeyExchange,ChangeCipherSpec这两个是不加密的,Finished是需要加密的。但TLS的加密是以record为单位的,一个record只能加密或不加密,不能其中一部分数据加密,另一部分不加密。所以在实现的时候,必须将Finished放入一个单独的record中,另外,在ChangeCipherSpecFinished之间,也需要将连接状态从明文状态转换到加密状态,就需要停顿一下。

但是,并不一定每个实现都能很好的遵循”将Finished放入单独的record中发送”这个约定,这样就在协议设计的时候添加了这样的冗余,相当于使用ChangeCipherSpecClientKeyExchangeFinished强制分配到两个record中。

3. TLS1.3的ChangeCipherSpec

TLS1.3中并不需要该消息,因为协议本身保证了在状态转换前发送的消息都是确定的,比如握手消息在ClientHello, ServerHello之后都是加密的,应用消息在发送完Finished之后也都是加密的,而且TLS1.3的秘钥推导跟之前版本的也都不一样,不需要CCS这样的冗余设计。但为了兼容性,还是保留了一些。

ChangeCipherSpec是TLS1.2及之前的协议设计的冗余消息,目的是从协议上避免实现时的流水线停顿问题。

参考


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK