zoukankan      html  css  js  c++  java
  • SSL (Secure Sockets Layer)

    本文转载自SSL (Secure Sockets Layer)

    TLS简介

    The Transport Layer Security (TLS) protocol aims primarily to provide secure and data integrity between two communicating computer applications.

    TLS位于TCP之上(也有基于UDP的,称为DTLS,这里不讨论它),如图 1 所示。

    ssl_desc.png

    Figure 1: SSL/TLS协议所在层次

    TLS各个版本提出时间如表 1 所示。

    Protocol Published
    SSL 1.0 Unpublished
    SSL 2.0 1995
    SSL 3.0 1996
    TLS 1.0 1999
    TLS 1.1 2006
    TLS 1.2 2008
    TLS 1.3 2018

    1.1 TLS两个阶段

    TLS协议可分为两个阶段:
    1、握手(Handshake)阶段,其目的是通信双方约定在数据传输阶段使用的加解密算法及密钥(为效率考虑,在数据传输阶段会使用对称密钥算法);
    2、数据传输阶段,即发送到网络前加密数据,从网络收到数据后解密数据。

    TLS报文头

    TLS报文头占5字节,第1字节是类型(目前有4种类型),第2-3字节是版本(目前有4种版本),第4-5字节是长度(不包含报文头本身长度),其格式为:

             record type (1 byte)
            /
           /    version (1 byte major, 1 byte minor)
          /    /
         /    /         length (2 bytes)
        /    /         /
     +----+----+----+----+----+
     |    |    |    |    |    |
     |    |    |    |    |    | TLS Record header (5 bytes)
     +----+----+----+----+----+
    
    
     Record Type Values       dec      hex
     -------------------------------------
     CHANGE_CIPHER_SPEC        20     0x14
     ALERT                     21     0x15
     HANDSHAKE                 22     0x16
     APPLICATION_DATA          23     0x17
    
    
     Version Values            dec     hex
     -------------------------------------
     SSL 3.0                   3,0  0x0300
     TLS 1.0                   3,1  0x0301
     TLS 1.1                   3,2  0x0302
     TLS 1.2                   3,3  0x0303
    

    TLS 1.2 Handshake

    Handshake具体过程

    TLS1.2使用“两个来回”完成握手过程:

              TLS1.2 Handshake
    
              +-----+                              +-----+
              |     |                              |     |
              |     |        ClientHello           |     |
              |     o----------------------------> |     |
              |     |                              |     |
              |     |                              |     |
              |     |        ServerHello           |     |
              |     |       [Certificate]          |     |
              |     |    [ServerKeyExchange]       |     |
              |     |    [CertificateRequest]      |     |
              |     |      ServerHelloDone         |     |
              |     | <----------------------------o     |
      CLIENT  |     |                              |     |  SERVER
              |     |                              |     |
              |     |       [Certificate]          |     |
              |     |     ClientKeyExchange        |     |
              |     |    [CertificateVerify]       |     |
              |     |   ** ChangeCipherSpec **     |     |
              |     |         Finished             |     |
              |     o----------------------------> |     |
              |     |                              |     |
              |     |                              |     |
              |     |   ** ChangeCipherSpec **     |     |
              |     |         Finished             |     |
              |     | <----------------------------o     |
              |     |                              |     |
              +-----+                              +-----+
    

    下面来介绍一下Handshake的具体过程。
    第1步、客户端发送 ClientHello 报文。其主要作用是告诉服务器,本客户端所支持的TLS协议版本,以及所支持的加密算法等等。
    第2步、服务器发送 ServerHello 报文。其主要作用是服务器选择一个它认为安全的,且双方都支持的加密算法;如果服务器认为客户端所有支持的加密算法都不安全,则服务器可以发送一个ALERT报文(ALERT报文是TLS顶级报文,参见 1.2 )。
    第3步、服务器发送 Certificate 报文。其主要作用是服务器发送自己的证书给客户端。
    第4步、服务器发送 ServerKeyExchange 。其主要作用是提供一些信息,以便双方有足够的信息来约定一个数据传输阶段所使用的对称密钥算法的密钥。这个报文是可选的,如果使用Diffie-Hellman方式来约定密钥,则这个是必须的;如果是RSA方式来约定密钥,它可以省略,参见后面介绍的 ClientKeyExchange 报文。
    第5步、服务器发送 CertificateRequest 。其作用是开启“双向认证(Mutual authentication)”模式,即不仅客户端要验证服务器,而且服务器还要验证客户端。这种方式在https网站中很少使用,如果对https网站进行抓包分析,一般都不会有这个报文。
    第6步,服务器发送 ServerHelloDone 。其作用是告诉客户端
    第7步、客户端发送 Certificate 报文(仅当客户端收到了 CertificateRequest 时才发送,即服务器开启了双向认证)。其主要作用是客户端发送自己的证书给服务器。
    第8步、客户端发送 ClientKeyExchange 报文。其主要作用是提供一些信息,以便双方有足够的信息来约定一个数据传输阶段所使用的对称密钥算法的密钥。如果是RSA方式,则客户端生成一个对称密钥算法的密钥后,使用服务器的公钥进行加密后传送给服务器。如果是Diffie-Hellman方式,则传送必要信息以便双方可以按约定方式生成同一个密钥。
    第9步、客户端发送 CertificateVerify 报文(仅当客户端收到了 CertificateRequest 时才发送,即服务器开启了双向认证)。主要作用是客户端发送一段它签名的信息给服务器,这样服务器使用客户端的公钥就可以验证签名,从而验证客户端。
    第10步、客户端发送 ChangeCipherSpec 报文,告诉服务器你可以使用加密模式了。注: ChangeCipherSpec 报文不属于Handshake报文,它是TLS顶级报文。
    第11步、客户端发送 Finished 报文,告诉服务器我准备好加密通信了。
    第12步、服务器发送 ChangeCipherSpec 报文,告诉客户端你可以使用加密模式了。
    第13步、服务器发送 Finished 报文,告诉客户端我准备好加密通信了。至此,握手结束。

    单向认证和双向认证

    握手阶段,如果服务器发送了 CertificateRequest ,就意味着开启“双向认证”。和“单向认证”相比,“双向认证”在握手阶段多了下面3种报文:

    • 服务器发送的 CertificateRequest
    • 客户端发送的 CertificateCertificateVerify

    参考:An Introduction to Mutual SSL Authentication

    复用TLS协商结果:Session Identifier, Session Ticket

    当我们打开一个https网页时往往会发送几十个请求,难道要重复几十次TLS握手协商吗?当然不用, 有两种方案可以复用第一次请求的TLS协商结果:Session Identifier和Session Ticket。

    这里不详细介绍它们,可参考:
    https://en.wikipedia.org/wiki/Transport_Layer_Security#Resumed_TLS_handshake
    https://stackoverflow.com/questions/19939247/ssl-session-tickets-vs-session-ids

    Handshake报文格式

    Handshake报文格式如下所示:

                             |
                             |
                             |
           Record Layer      |  Handshake Layer
                             |                              |                              |
                             |                              |                              |
    +----+----+----+----+----+----+----+----+----+------ - -+----+----+----+----+------ - -+ ......
    | 22 |    |    |    |    |    |    |    |    |          |    |    |    |    |          |
    |0x16|    |    |    |    |    |    |    |    |message   |    |    |    |    |message   |
    +----+----+----+----+----+----+----+----+----+------ - -+----+----+----+----+------ - -+
      /             /--/--/  |     ---------            |     ---------            |
     /                /      |                                        
    type: 22         /       |        handshake message length     handshake message length
                    /             type                          type
                   /
             length: arbitrary (up to 16k)
    
    
     Handshake Type Values    dec      hex
     -------------------------------------
     HELLO_REQUEST              0     0x00
     CLIENT_HELLO               1     0x01
     SERVER_HELLO               2     0x02
     CERTIFICATE               11     0x0b
     SERVER_KEY_EXCHANGE       12     0x0c
     CERTIFICATE_REQUEST       13     0x0d
     SERVER_HELLO_DONE         14     0x0e
     CERTIFICATE_VERIFY        15     0x0f
     CLIENT_KEY_EXCHANGE       16     0x10
     FINISHED                  20     0x14
    

    注1:共有10种类型的Handshake报文,每种类型的具体格式可参考:Traffic Analysis of an SSL/TLS Session
    注2:多个Handshake报文可以组合为一个TLS Record,上面演示中就有两个Handshake报文。

    ClientHello

    ClientHello报文如下所示:

         |
         |
         |
         |  Handshake Layer
         |
         |
    - ---+----+----+----+----+----+----+------+----+----------+--------+-----------+----------+
         |  1 |    |    |    |    |    |32-bit|    |max 32-bit| Cipher |Compression|Extensions|
         |0x01|    |    |    |  3 |  1 |random|    |session Id| Suites |  methods  |          |
    - ---+----+----+----+----+----+----+------+----+----------+--------+-----------+----------+
      /  |      ---------    ----                    
     /                                              SessionId
    record         length        SSL/TLS            
    length                       version         SessionId
                type: 1       (TLS 1.0 here)       length
    
    
    
    CipherSuites
    
    +----+----+----+----+----+----+
    |    |    |    |    |    |    |
    |    |    |    |    |    |    |
    +----+----+----+----+----+----+
      -----   -----    ----
                            
          length    cipher Id  cipherId
    
    
    Compression methods (no practical implementation uses compression)
    
    +----+----+----+
    |    |    |    |
    |  0 |  1 |  0 |
    +----+----+----+
      -----    
                 
     length: 1    cmp Id: 0
    
    
    Extensions
    
    +----+----+----+----+----+----+----- - -
    |    |    |    |    |    |    |
    |    |    |    |    |    |    |...extension data
    +----+----+----+----+----+----+----- - -
      -----   -----    ----
                            
        length    Extension  Extension data
                     Id          length
    

    Server Name Indication (SNI)

    在TLS握手时,客户端发送的ClientHello中不包括服务器的域名,这一般不会有问题。但随着HTTP服务器开启虚拟主机支持后,每个服务器通过相同的IP地址可以为很多个网站提供服务。这样服务器在发送Certificate报文时不知道应该向客户端提供哪一个网站的证书。2006年,TLS协议增加了Server Name Indication (SNI) 扩展,允许客户端在ClientHello报文中带上它所请求的域名,这样服务器就知道客户端想访问哪个网站了,从而提供对应的证书。

    参考:https://blog.csdn.net/makenothing/article/details/53292335

    Application Layer Protocol Negotiation (ALPN)

    Application Layer Protocol Negotiation (ALPN, RFC 7301),旨在将原来应用层协议中的协商,提前合并到TLS握手时完成,以减少一次往返时间(即不再需要应用层协议中的协商了)。

    ALPN最初是为Google SPDY协议(现已标准化为HTTP/2)而提出的。我们以HTTP/2为实例来说明ALPN。假设TLS握手完成了,接下来客户端和服务端就应该开始进行正常的HTTP通信了,但是客户端认为HTTP协议比较慢,在请求内容之前先向服务端提出“我们能不能使用HTTP/2协议”。服务端会根据自己支持HTTP/2的情况给出回答,之后客户端会根据服务端的答复,使用HTTP或HTTP/2向服务端请求内容。可以看到这个过程中又多了一次协商升级协议的往返,导致客户端拿到返回结果的延迟更大了。

    为了优化这一点,在HTTP使用TLS加密的时候,会使用ALPN扩展,把升级HTTP协议的请求放在ClientHello的ALPN Extension字段中,服务端在ServerHello的ALPN Extension字段中回复说“我支持HTTP/2”。这样TLS握手之后,客户端就可以直接按HTTP/2发起请求而不必多一次往返了。

    ALPN 检测服务器是否支持 HTTP 2

    前面说过,在 TLS 握手阶段,客户端可通过 ALPN 来检测服务器是否支持 HTTP 2。下面以浏览器访问 “https://tmail.com” (它已经支持了HTTP 2)为例,使用 Wireshark 进行抓包验证。

    浏览器第一次发送 ClientHello 报文时,在 ALPN 中携带了浏览器支持的版本,h2 代表浏览器支持 HTTP 2 协议,如图 2 所示。

    ssl_client_hello.jpg

    Figure 2: ClientHello

    服务器在返回 ServerHello 报文时,在 ALPN 中返回了 h2,表示服务器支持 HTTP 2 协议,如图 3 所示。

    ssl_server_hello.jpg

    Figure 3: ServerHello

    这样,建立 TLS 连接后,浏览器就知道了服务器已经支持 HTTP 2,下一步,可以直接发送“GET / HTTP/2”这样的 HTTP 报文了。

    TLS 1.3

    2018年8月10日,IETF发布了TLS 1.3(RFC 8446)。这次是TLS协议的第一次重大改革,带来了重大的安全性和性能改进。

    TLS 1.3 只需要一个RTT(来回传输一次的时间)就能完成握手,相比TLS 1.2省去了一个RTT(如图 45 所示,图片摘自:https://www.cloudflare.com/learning-resources/tls-1-3/ )。并且TLS 1.3支持“0-RTT”模式,在该模式下客户端可以在握手的同时发送数据,极大地加快了https网页的加载速度。

    ssl_tls1.2vs1.3_a.png

    Figure 4: TLS 1.2握手完成需要“来回两次”

    ssl_tls1.2vs1.3_b.png

    Figure 5: TLS 1.3握手完成仅需“来回一次”

    参考

    The Transport Layer Security (TLS) Protocol Version 1.2
    Traffic Analysis of an SSL/TLS Session
    使用wireshark观察SSL/TLS握手过程--双向认证/单向认证

  • 相关阅读:
    element表格添加序号
    ZOJ 3822 Domination(概率dp)
    HDU 3037(Lucas定理)
    HDU 5033 Building(单调栈维护凸包)
    HDU 5037 Frog(贪心)
    HDU 5040 Instrusive(BFS+优先队列)
    HDU 5120 Intersection(几何模板题)
    HDU 5115 Dire Wolf(区间dp)
    HDU 5119 Happy Matt Friends(dp+位运算)
    C++ string详解
  • 原文地址:https://www.cnblogs.com/yungyu16/p/13265996.html
Copyright © 2011-2022 走看看