前言

如果还没尝试过使用wiresharp的话,可以参照我之前写过的文章《wireSharp的基本用法》 (opens new window)

本篇文章不会详细说TLS的内容,请结合我上一篇文章《深入TLS/SSL协议》 (opens new window)一起观看。

Handshake

基本概念

TLS1.2中的握手过程主要有三个目的:

  • 验证身份
  • 达成安全套件共识
  • 传递密钥

如图所示:

1、客户端发送一个Client Hello,包含:

  • 协议版本号。
  • 客户端生成的随机数-Client random
  • 客户端所支持的安全套件列表。

2、服务器回一个Server Hello,包括:

  • server所选择的安全套件。
  • server发送自己的数字证书-server Certificates
  • server发送自己生成的公钥-serverKey

3、客户端发送自己生成的公钥-clientKey
4、客户端与服务器根据自己的私钥与对方的公钥生成对称加密的密钥。
5、进行加密通讯

使用wiresharp抓包分析

下面抓取www.juejin.im为例:

1、Client hello

  • 协议版本号Version:TLS 1.2
  • 随机数Random
  • 支持17种安全套件的列表

2、Server hello中:

  • 协议版本号Version:TLS 1.2

  • 选中了一个安全套件:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

  • 随机数Random

  • 发送数字证书:

  • 发送server的公钥以及所用的签名算法:

3、Client发送自己的公钥

4、clientserver根据自己的私钥与对方的公钥生成对称加密的密钥

5、Change Cipher Spec这一步是客户端通知服务端后面再发送的消息都会使用前面协商出来的密钥加密了并通知server握手结束。

6、Change Cipher Spec这一步是服务端通知客户端后面再发送的消息都会使用加密并通知client握手结束。

TLS1.3握手

TLS1.3中,大大减少了所支持的安全套件。比如在openssl1.1中只支持5种安全套件

  • TLS13-AES-256-GCM-SHA384
  • TLS13-CHACHA20-POLY1305-SHA256
  • TLS-AES-128-GCM-SHA256
  • TLS-AES-128-CCM-8-SHA256
  • TLS-AES-128-CCM-SHA256

TLS1.3握手的变化:
由于安全套件的减少,client可以在第一次请求中将5种安全套件全部生成一对密钥,将5种publicKey发送给server,然后server选择其中一种安全套件来生成自己的一对密钥。从而相比上面说的TLS1.2的握手过程减少了一次RTT

握手过程的优化

TLS握手中消耗的那一个或两个RTT时间是对于安全性而言的。

但对于应用层的信息传递而言并没有意义。

所以TLS提供了许多种手段来减少握手过程中所消耗的RTT的时间。比如:session缓存、ticket票据等

session缓存

第一次握手后服务器会生成一个sessionID,然后传给浏览器。

在一定时间内,比如几个小时、几天内。浏览器携带这个sessionID再次访问服务器时,服务器会从缓存中提取这个sessionID所指向的加密密钥。没有必要再次根据ECDH协议生成新的密钥,从而减少消耗的RTT时间。

下面以百度站点为例:
当再次访问百度站点时,client hello就会携带一个sessionID

client Hello步骤之后直接到了Change Cipher Spec。并没有进行DH或者ECDH密钥交换协议

Change Cipher Spec里面就告诉Client,使用之前的密钥

ticket票据

sesion机制不同的是,ticket机制不需要server花费缓存来存放。而是基于一个独特的密码,这个密码是集群中所共享的。基于这个密码将ticket解密后,就可以获取到上一次生成的密钥。

TLS1.3中的0RTT握手

所谓0RTT,指的是:第一次请求时就携带GET数据,在一次RTT后就马上得到RESPONSE。握手时间就是0RTT了。

事实上这也是第二次握手中才有的。当第一次握手时,clientserver就会把密钥信息缓存下来。第二次访问时,基于第一次缓存的,基于一定时间内有效的信息对报文进行加密。

重放攻击

无论是sessionticket还是TLS1.3中的0RTT都面临着一个危险:重放攻击
如图所示:

如果Client发送一个使用上一次的密钥加密的post请求给server,而通常一个post请求是会改变数据库的。

如果这个报文被中间人获取下来了,而且并不需要解密这份报文。然后在随后的时间内,不断的发送这个报文,就可以不断的改变数据库以造成攻击效果。

所以设定一个合适的过期时间是必要的。