天天看点

解密TLS协议全记录之TLS协议剖析记录引言预备知识TLS1.2协议解析TLS1.3协议学习

引言

这篇文章是学习TLS协议的学习总结, 根据奥卡姆剃刀原理, 文章会尽可能记录相对有价值的内容,

预备知识

想要解密TLS的首当其冲的点,便是要深入了解TLS中的RFC协议文档。

  • 学习网络协议之前,必须先找对最基本的协议学习网站,

    rfc协议官网 https://www.rfc-editor.org

    ietf协议官网 https://www.ietf.org/ ,其实这个网站,我经常搜索不出比较理想的文件,标题不直观,杂七杂八的会议记录文件一大堆夹杂在规范文件之中。

  • 通过上面的网站,我们可以获取到tls的几个协议说明链接.

    TLS1.0: https://www.rfc-editor.org/rfc/rfc2246.html

    TLS1.2: https://www.rfc-editor.org/rfc/rfc5246.html https://tools.ietf.org/html/rfc5246

    TLS1.3草案:https://tools.ietf.org/html/draft-ietf-tls-tls13-23

  • 本博客会以tls1.2为主, tls1.3协议为辅,毕竟tls1.3 毕竟还处于草稿设计阶段。

TLS1.2协议解析

在描述整体的通信流程之前,先了解tls中将会使用的一些协议描述。

报文中的前几个字段的描述, 这是每个TLS包文,都会拥有的参数

ContentType type:表示当前的协议类型, 比如握手协议,警告协议。

ProtocolVersion version:表示当前TLS的协议版本。

Length:表示接下来的数据段(fragment)的尺寸大小。

Fragment: 用于填充TLS协议的各类子协议内容和应用的通信数据。

并且,了解整体通信的时序图,也是相当有必要的。

Client                                               Server

      ClientHello                  -------->
                                                      ServerHello
                                                     Certificate*
                                               ServerKeyExchange*
                                              CertificateRequest*
                                   <--------      ServerHelloDone
      Certificate*
      ClientKeyExchange
      CertificateVerify*
      [ChangeCipherSpec]
      Finished                     -------->
                                               [ChangeCipherSpec]
                                   <--------             Finished
      Application Data             <------->     Application Data
           

1. Handshake Protocol协议

Handshake Protocol: 会话状态(session state)的加密参数由TLS握手协议产生, 这个过程会选择加密套件,压缩方法, 做相互之间的证书认证,除此之外,将会产生客户端的随机数和服务器的随机数,使用加密技术去生成共享密钥, 目前主要是 RSA和DH加密技术。

notice: 在该协议下的多个子协议报文,服务器和客户端可以选择同时发送,也可以按序拆开发送,查阅wireshark报文的时候要注意这一点。

0. Client Hello消息中,客户端将会把自己支持的密钥套件发送给服务端, 服务端将会从中选择一个来进行通信,一般来说服务器都会支持,而且一般来说, 服务器一般会选择自己支持的或者说自己配置的(可查看下文的注意高亮文本),不会去关注客户端的报文列表。

解密TLS协议全记录之TLS协议剖析记录引言预备知识TLS1.2协议解析TLS1.3协议学习

此处的版本信息指的是客户端支持的最新的协议版本号,官方说为了防止RollBack攻击。

解密TLS协议全记录之TLS协议剖析记录引言预备知识TLS1.2协议解析TLS1.3协议学习

注意: 在TLS中有规定, 客户端的加密套件只是参考选择, 服务器可以选择不选,而选择服务器配置和支持的加密套件。之前参考以下博客: https://blog.csdn.net/appletreesujie/article/details/54972999, 其中提到 通过命令

curl -k --ciphers rsa_rc4_128_sha https://10.1.1.1/url_sample

可以设置客户端加密套件,可是抓包时,发现curl命令发出去的包并不会指定该加密套件,粗滤看了一下代码,觉得应该还不支持, 而且curl命令的cipher指定的名字特别不规范, 完全不按照openssl以及TLS规定的名字来,要另外去查看代码获得。

1.0 Client Key Exchange Message的报文一般跟随客户端的证书一起发送,如果服务端有请求的话, 这个报文最大意义在于,在这个过程中, 通信的预主密钥将会被设置,并根据密钥交换算法, 要么是通过RSA密钥算法来交换,要么是通过DH密钥算法来通过参数交换(还有PSK密钥交换算法,不做赘述),然后计算得到密钥, 交换密钥算法的几种类型如下:

select (KeyExchangeAlgorithm) {

case rsa:

EncryptedPreMasterSecret;

case dhe_dss:

case dhe_rsa:

case dh_dss:

case dh_rsa:

case dh_anon:

ClientDiffieHellmanPublic;

} exchange_keys;

1. 理解RSA交换密钥之前,需要简单了解RSA算法,该算法可以通过openssl产生一个随机的私钥, 然后通过私钥,可以得到公钥, 这个过程是不可逆的, 也就是说只有私钥可以解密, 所以,RSA也是非对称加密算法的一种。

2. 那么DH算法的话,就是通信双方都有一套自己的公钥和私钥,通过交换公钥之后,利用协商好的参数,然后使用DH算法计算,可以得到一个一样的密钥。下面引用维基百科的一个例子。

3. 还有一种PSK密钥交换算法, 基本原理就是使用 PSK 时,AP 和客户端必须配置相同的密钥或加密密码。AP 发送一个随机字符串到客户端。客户端接受该字符串,根据密钥对其进行加密(或编码),然后发送回 AP。AP 获取加密的字符串,并使用其密钥解密(或解码)。如果从客户收到的字符串在解密后与原来发送给客户端的字符串匹配,就允许该客户端连接。

愛麗絲與鮑伯协定使用 p=23以及base g=5

(参数一般有服务器下发)

.

愛麗絲选择一个秘密整数a=6

(类似私钥值)

, 计算A = ga mod p并发送给鮑伯。

A = 56 mod 23 = 8.

(类似公钥值)

鮑伯选择一个秘密整数

b=15

, 计算B = gb mod p并发送给愛麗絲。

B = 515 mod 23 = 19.

愛麗絲计算s = B a mod p

196 mod 23 = 2

(共享密钥)

.

鮑伯计算s = A b mod p

815 mod 23 = 2.

1.1 如果是 RSA加密算法来交换密钥的话, 客户端将会生成一个随机48字节的预主密钥, 然后通过

服务器的证书中的公钥

加密发送给服务器,RSA不仅可以用来加密解密, 还可以用来数字签名证书哦, 可以查看我的另一篇文章, openssl的使用详解。

报文内容如下图的Encrypted PreMaster所示。

解密TLS协议全记录之TLS协议剖析记录引言预备知识TLS1.2协议解析TLS1.3协议学习

1.2 如果是DH 加密算法来交换密钥的话,客户端将会生成DH密钥中所需的Public Key(Yc)发送给服务器,

此处有一点疑问,在客户端DH算法每次都要重新生成密钥, 而没有类似RSA算法提前生成证书来进行握手的话,那么每次要额外去计算一个DH算法的key value,会不会很浪费时间?答:因为DH每次生成key的话,确实浪费时间,所以基于椭圆曲线的ECDH算法应运而生, 此外,DH握手每次都会去生成不同的密钥,具有前向保密,RSA一旦通过公钥和加密信息去破解服务器私钥的话,就可以从握手中得到对称密钥,

之后客户端和服务端将分别使用自己的私钥和对方的公钥来计算预主密钥,也就是TLS协议中指的The negotiated key(Z) ,所以DH算法也算是对称加密算法的一种。 客户端的public key如下所示:

解密TLS协议全记录之TLS协议剖析记录引言预备知识TLS1.2协议解析TLS1.3协议学习

注意:可能有人会好奇,为什么有的报文只有

client key exchange message

,有的还有

server key exchange message

, 因为如果是DH加密算法来交换密钥,服务端还要发送一个

server key exchange message

的报文来下发DH算法计算需要的额外参数以及Pub key。如下图所示:

解密TLS协议全记录之TLS协议剖析记录引言预备知识TLS1.2协议解析TLS1.3协议学习

1.3 那么当客户端和服务端之间得到密钥之后, 如何计算主密钥:

疑问: 既然有预主密钥,为何还要再浪费计算主密钥? 预主密钥一样可以达到一样的加密效果? 没时间深究,有了解的人可以联系我

master_secret = PRF(pre_master_secret, “master secret”, ClientHello.random + ServerHello.random) [0…47];

1.4 当服务器发送server hello done的报文的时候, 表示服务端的握手通信已经完成,服务器将会等待客户端的回复, 如果服务器发送了CertificateRequest的消息的话, 客户端一定要将自身具有的证书回复给服务器

1.5 当建立会话之后,服务器将会产生

new session ticket

来表示当前的会话窗口号,那么, 当客户端和服务端需要进行之前的会话的时候,则将想要恢复对话的窗口号(session id)发送给服务器, 这样可以避免再做一次完整的握手通信过程,服务器和客户端直接使用先前得到的密钥进行网络通信即可,恢复通信的报文如下, 省略了很多报文通信,节约了时间:

疑问: wireshark 有时候无法解密是不是就是因为报文通信的密钥使用的是之前商议好的密钥?

A: 确实如此,如果是使用RSA密钥交换算法,那么报文中一定要包含ClientKeyExchange的消息, 这样wireshark 才能拿到客户端产生的随机数(预主密钥)

解密TLS协议全记录之TLS协议剖析记录引言预备知识TLS1.2协议解析TLS1.3协议学习

2.Change Cipher Spec 协议

Change Cipher Spec Protocol : 该协议是为了提示通信的对端, 接下来的报文通信,将会使用刚协商的新的加密策略以及加密密钥,这个协议会从握手协议独立出来的主要原因是为了避免通道拖延,通信滞后。

3. Alert 协议:

Alert Protocol: 该协议用来传达警报消息的严重性以及说明,比如, 证书过期, 证书未知等, 必要的时候,会中断链接,警告消息同样会使用当前的加密策略进行加密和压缩

4. 其他, 查看官方协议。

TLS1.3协议学习

  • TLS1.3的协议暂时关注的不多, 毕竟还只是草稿协议。
  • 个人认为最明显的一点在于, TLS 1.3 的握手不再支持静态的 RSA 密钥交换,这意味着可以使用带有前向安全的 Diffie-Hellman 进行全面握手。并且使用 TLS 1.3 协议只需要一次往返( 1-RTT )就可以完成握手,这句话看一下协议的时序图应该可以理解。
  • 为什么TLS1.3 不再支持RSA密钥交换, 看下面的时序图,可以发现,客户端直接先发key出去, 之后,服务器才下发证书, 那么就意味着此时的key无法被RSA算法中提到, 必须利用证书的公钥进行加密, 那么就只能是时DH算法中的public value,才能直接暴露出来。
Client                                               Server

   Initial Handshake:
          ClientHello
          + key_share               -------->
                                                          ServerHello
                                                          + key_share
                                                {EncryptedExtensions}
                                                {CertificateRequest*}
                                                       {Certificate*}
                                                 {CertificateVerify*}
                                                           {Finished}
                                    <--------     [Application Data*]
          {Certificate*}
          {CertificateVerify*}
          {Finished}                -------->
                                    <--------      [NewSessionTicket]
          [Application Data]        <------->      [Application Data]


   Subsequent Handshake:
          ClientHello
          + key_share*
          + pre_shared_key          -------->
                                                          ServerHello
                                                     + pre_shared_key
                                                         + key_share*
                                                {EncryptedExtensions}
                                                           {Finished}
                                    <--------     [Application Data*]
          {Finished}                -------->
          [Application Data]        <------->      [Application Data]
           

附录:

  • MAC(message Authentication code) 用来保证信息的完整性。
  • HMAC: Keyed-Hashing for Message Authentication
  • PRF(This pseudorandom function), PRF, based on HMAC. This PRF with the

    SHA-256 hash function is used for all cipher suites defined in this

    document and in TLS documents published prior to this document when

    TLS 1.2 is negotiated. New cipher suites MUST explicitly specify a

    PRF and, in general, SHOULD use the TLS PRF with SHA-256 or a

    stronger standard hash function

继续阅读