TLS握手

大番茄 2020年12月02日 369次浏览

今天被问到ssl协商过程,思路有点混乱,回来又看了看,然后抓包瞧了瞧。

根据抓包结果,过一下流程。一共是4次握手。

图片里的内容就是使用curl访问一下https的网页产生的。
浏览器因为是多线程会导致好多连接,所以用的curl命令。
只是寻常的https访问, 没有双向加密之类的。

image.png
标准文档:
TLS 1.2: https://tools.ietf.org/html/rfc5246
TLS 1.0: https://tools.ietf.org/html/rfc2246

一、Client Hello

有可以兴趣看看标准文章,我是连蒙带翻译的,真羡慕英语好的同学。
https://tools.ietf.org/html/rfc5246#section-7.4.1.2

image.png

image.png
向服务器发送:
1、28字节的随机数。图片里的是十六进制,两位一个字节,正好28个字节。
2、客户段支持的加密套件列表
3、客户端支持的压缩算法列表
4、客户端希望使用的TLS版本,应该是客户端支持的最新版本。
5、session ID, 用于会话复用。比如在进行第二次建立tls会话的时候,如果客户端设置了session id,服务端也正好有缓存这个会话,就可以直接会话已建立的状态。
6、扩展内容列表

二、Server Hello、Certificate、Server Hello Done

一般都是一起说的,毕竟都是属于Server Hello阶段。而且有的服务器可能是合并在一起发的。
我这里使用的是RSA算法, 如果是DH算法,听说还会多出一层Server Key Exchange。

hello:

https://tools.ietf.org/html/rfc5246#section-7.4.1.3

image.png
如果服务端没有找到匹配的算法,会握手失败。

回应的信息:
1、服务端可匹配的最高TLS版本。
2、28字节随机数,并且必须与client hello发来的不一样。
3、session id, client hello 中如果发送了session id,服务端也可以在会话缓存里查找到匹配的会话信息,并且也愿意使用。会使用相同的id值,以响应客户端可以继续使用之前的会话。
4、从客户端加密套件列表里选择使用的加密套件。对于使用session_id恢复的会话,会使用会话里的值。
5、从客户端压缩算法列表里选择使用的压缩算法。对于使用session_id恢复的会话,会使用会话里的值。
6、扩展内容列表,只有客户端提供的才会添加。

Certificate、Server Hello Done:

https://tools.ietf.org/html/rfc5246#section-7.4.2

image.png
服务器发给客户端的证书, 证书的类型必须适合所选加密套件里的算法。

Server Hello Done:
https://tools.ietf.org/html/rfc5246#section-7.4.5

只是表示Server Hello结束了,服务端开始等待客户端继续完成握手。
客户端收到以后就开始检查服务端证书是否有效,如果有问题,会提示用户是否继续。以及验证服务端返回的参数是否可以接受。

三、Client Key Exchange、Change Cipher Spec、Encrypted Handshake Message

https://tools.ietf.org/html/rfc5246#section-7.4.9
https://tools.ietf.org/html/rfc5246#section-7.1

image.png

Client Key Exchange

客户端生成premaster秘钥,并且使用证书里的公钥加密。
客户端使用这组秘钥,以及第一次发给服务器的随机数,还有服务器返回的随机数, 共同计算出来加密数据的主秘钥。
服务端使用私钥解密premaster, 然后根据前两个随机数,计算出相同的主秘钥。

Change Cipher Spec

修改加密规范。 之后的通信使用确定的加密套件以及计算出的秘钥。

Encrypted Handshake Message

使用确定的加密规范加密握手过程中的信息,不包括本次发送的信息, 发送给服务端已确定中间数据的完整性。

四、Change Cipher Spec、Encrypted Handshake Message

image.png

服务端回复信息,跟客户端意思一样。 只不过服务端加密的握手信息因为比客户端多一步,所以数据不一样。

上面tls的握手就已经完成了

这里出现了一个New Session Ticket, 也是第一次见, 查了一下发现也是用于tls会话复用的,与session id一个功能,但实现方式不一样。
session id 是客户端与服务端都要存储这个信息。 而session ticket是服务端把握手成功以后的参数加密以后发给客户端, 客户端以后想要复用就把session ticket发给服务端, 服务端验证没问题就可以恢复会话。
有兴趣可以看看这个,我也是简单看了一部分,时间问题也不能完完整整看一遍。在这里做个记录:
https://blog.csdn.net/justinzengTM/article/details/105491809?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-3&spm=1001.2101.3001.4242