前言
上一篇文章刨根问底系列之https到底是如何防篡改的?面试必备详细解释了http为什么不安全,https为什么安全,并大致介绍了https通信过程是如何加密的,以及什么是数字证书,什么是签名,如有不了解的,可以先看看上一篇文章,本篇文章主要从协议层面介绍https的详细握手过程。如果说上一篇文章是辅助你理解https的加密过程,那这一篇文章就是拿真实网络数据包来分析https的详细握手过程,如果你能和上一篇的过程一一对应上,那恭喜你,也恭喜我,大家都没有浪费时间。
进入正题之前,先解答一下上篇文章留的两个问题
- 为什么charles等抓包工具或者浏览器控制台看到的https返回是明文的? 首先说明一下,https其实相当于http+tsl,(tsl和ssl只是不同的版本称呼问题,暂且这么理解),大家都知道,http是明文操作,那也就是说所有的加密解密操作都在tls这边,具体关系可以参看下面这张图
- 浏览器是属于应用层之上的应用吧,所以浏览器控制台的输出都是已经经过tls解密过的。 那为什么charles等抓包工具看到的也是明文的呢?是不是也是因为charles是应用层之上的应用呢?不尽然如此!charles在抓包过程中是起到了中间代理的作用,浏览器=====》Charles======》服务器,charles相对于浏览器来说,是服务端,相对于服务端来时,是客户端。charles在抓取https的包时,是需要浏览器先安装并信任自己的证书的(相当于服务器的证书),具体可看下图 所以,能看出来,之所以charles能看到明文,是因为你主动信任了他的证书
- 为什么制作数字签名时需要hash一次? 其实仔细想一想,如果制作签名的时候不做hash,有什么影响吗?其实还真没有影响,还是能正常运行,给证书明文签名和给明文的hash签名,不会给验证有任何影响。但为什么要做一次hash呢?还记得上篇文章上提到过,非对称加密是非常耗时和耗性能的,对一个字符加密和对100个字符加密哪个更快一些,掰着大拇指想一想也是越短加密越快,所以原因出来了,证书的明文基本都很长,但是经过hash之后都很短,而且基本都是固定的长度了,所以出于性能的考虑,在制作签名时需要hash一次
好,问题回答完毕,如有疑问,先冷静分析一下,接下来进入正题
https的详细握手过程
https在七层协议里面属于应用层,他基于tcp协议,所以,https握手的过程,一定先经过tcp的三次握手,tcp链接建立好之后,才进入https的对称密钥协商过程,对称密钥协商好之后,就开始正常的收发数据流程。
接下来我就拿实际网络数据包来解释https的整个详细的握手过程
于是我打开wireshark抓包工具,并随手打开命令行,怯意的输入了如下一行命令
curl https://www.baidu.com
上面其实涉及到两个问题
- 为什么是wireshark,而不是fiddler 或者 charles fiddler 和charles主要是用于抓取应用层协议https/http等上层的应用数据,都是建立链接成功后的数据,而wireshark是可以抓取所有协议的数据包(直接读取网卡数据),我们的目的是抓取https建立链接成功前的过程,所以我们选择wireshark
- 为什么是用curl, 而不是在浏览器打开https://www.baidu.com curl是只发送一个请求,如果是用浏览器打开百度,那百度页面里面的各种资源也会发送请求,容易造成很多不必要的数据包
好,重点来了,开始上图:
上面两张图就是用curl请求https://www.baidu.com用wireshark抓到的所有数据包,是不是有点慌,哈哈
遇到凡事不要慌,接下来待我给你慢慢道来(ack消息属于tcp协议里面的确认报文,不做解释)
第一步
解释说明:tcp三次握手,这个不做解释,如果这块不清楚,比如ack,seq,mss,win都代表什么意思,这个可以在互动区留言,我视情况专门写几篇tcp的文章(这块太大了,没几篇是介绍不完的)
第二步:客户端发送client_hello
解释说明:客户端发送client_hello,包含以下内容(请自行对照上图)
1. 包含TLS版本信息
2. 随机数(用于后续的密钥协商)random_C
3. 加密套件候选列表 4. 压缩算法候选列表 5. 扩展字段 6. 其他
第三步:服务端发送server_hello
解释说明:服务端收到客户端的client_hello之后,发送server_hello,并返回协商的信息结果
1. 选择使用的TLS协议版本 version
2. 选择的加密套件 cipher suite
3. 选择的压缩算法 compression method
4. 随机数 random_S 5. 其他
第四步:服务端发送证书
解释说明:服务端发送完server_hello后,紧接着开始发送自己的证书(不清楚证书是什么的,可以移步到上一篇文章),从图可知:因包含证书的报文长度是3761,所以此报文在tcp这块做了分段,分了3个报文把证书发送完了
问自己: 1. 分段的标准是什么? 2. 什么时候叫分段,什么时候叫分片? 3. 什么是MTU,什么是MSS
第五步:服务端发送Server Key Exchange
解释说明:对于使用DHE/ECDHE非对称密钥协商算法的SSL握手,将发送该类型握手。RSA算法不会进行该握手流程(DH、ECDH也不会发送server key exchange),也就是说此报文不一定要发送,视加密算法而定。SSL中的RSA、DHE、ECDHE、ECDH流程与区别可以参考此篇文章
第六步:服务端发送Server Hello Done
解释说明:通知客户端 server_hello 信息发送结束
第七步:客户端发送.client_key_exchange+change_cipher_spec+encrypted_handshake_message
解释说明: 1. client_key_exchange,合法性验证通过之后,向服务器发送自己的公钥参数,这里客户端实际上已经计算出了密钥 2. change_cipher_spec,客户端通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信 3. encrypted_handshake_message,主要是用来测试密钥的有效性和一致性
第八步:服务端发送New Session Ticket
解释说明:服务器给客户端一个会话,用处就是在一段时间之内(超时时间到来之前),双方都以协商的密钥进行通信。
第九步:服务端发送change_cipher_spec
解释说明:服务端解密客户端发送的参数,然后按照同样的算法计算出协商密钥,并通过客户端发送的encrypted_handshake_message验证有效性,验证通过,发送该报文,告知客户端,以后可以拿协商的密钥来通信了
第十步:服务端发送encrypted_handshake_message
解释说明:目的同样是测试密钥的有效性,客户端发送该报文是为了验证服务端能正常解密,客户端能正常加密,相反:服务端发送该报文是为了验证客户端能正常解密,服务端能正常加密
第十一步:完成密钥协商,开始发送数据
解释说明:数据同样是分段发送的
第十二步:完成数据发送,4次tcp挥手
解释说明:红框的意思是:客户端或服务器发送的,意味着加密通信因为某些原因需要中断,警告对方不要再发送敏感的数据,服务端数据发送完成也会有此数据包,可不关注
结语
最后用一张图来说明以下过程