zoukankan      html  css  js  c++  java
  • 04.安全-TLS1.2连接过程

    TLS 握手的前几个消息都是明文的,能够在 Wireshark 里直接看。

    但只要出现了“Change Cipher Spec”,后面的数据就都是密文了,看到的也就会是乱码,不知道究竟是什么东西。

    为了更好地分析 TLS 握手过程,可以再对系统和 Wireshark 做一下设置,让浏览器导出握手过程中的秘密信息,这样 Wireshark 就可以把密文解密,还原出明文。

    首先,你需要在 Windows 的设置里新增一个系统变量SSLKEYLOGFILE,设置浏览器日志文件的路径,比如

    D:http_studylogsslkey.log

    然后在 Wireshark 里设置“Protocols-TLS”
    (较早版本的 Wireshark 里是“SSL”),在“(Pre)-Master-Secret log filename”里填上刚才的日志文件

    ECDHE握手过程


    在 TCP 建立连接之后,浏览器会首先发一个“Client Hello”消息,也就是跟服务器“打招呼”。
    里面有客户端的版本号、支持的密码套件,还有一个随机数(Client Random),用于后续生成会话密钥

    Transport Layer Security
        TLSv1.2 Record Layer: Handshake Protocol: Client Hello
            Content Type: Handshake (22)
            Version: TLS 1.0 (0x0301)
            Length: 512
            Handshake Protocol: Client Hello
                Handshake Type: Client Hello (1)
                Length: 508
                Version: TLS 1.2 (0x0303)
                Random: deb646e741a099b49bfef08f38871a4ac8d86b1f265ea6dc…
                Session ID Length: 32
                Session ID: 559393da63fd63f325d1f52088aa649401260c65f1e499fc…
                Cipher Suites Length: 34
                Cipher Suites (17 suites)
                Compression Methods Length: 1
                Compression Methods (1 method)
                Extensions Length: 401
                Extension: Reserved (GREASE) (len=0)
                Extension: server_name (len=19)
                Extension: extended_master_secret (len=0)
                Extension: renegotiation_info (len=1)
                Extension: supported_groups (len=10)
                Extension: ec_point_formats (len=2)
                Extension: session_ticket (len=0)
                Extension: application_layer_protocol_negotiation (len=14)
                Extension: status_request (len=5)
                Extension: signature_algorithms (len=20)
                Extension: signed_certificate_timestamp (len=0)
                Extension: key_share (len=43)
                Extension: psk_key_exchange_modes (len=2)
                Extension: supported_versions (len=11)
                Extension: compress_certificate (len=3)
                Extension: Reserved (GREASE) (len=1)
                Extension: padding (len=202)
    

    作为“礼尚往来”,服务器收到“Client Hello”后,会返回一个“Server Hello”消息。

    把版本号对一下,也给出一个随机数(Server Random),
    然后从客户端的列表里选一个作为本次通信使用的密码套件,在这里它选择了“TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384”

    Transport Layer Security
        TLSv1.2 Record Layer: Handshake Protocol: Server Hello
            Content Type: Handshake (22)
            Version: TLS 1.2 (0x0303)
            Length: 112
            Handshake Protocol: Server Hello
                Handshake Type: Server Hello (2)
                Length: 108
                Version: TLS 1.2 (0x0303)
                Random: 306ba0a553a042f119e52473b67c6e293f3ee61012fff8ff…
                Session ID Length: 32
                Session ID: 27e4112dd0e1299b7fd853c7787c16308bf03435a620a8fd…
                Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
                Compression Method: null (0)
                Extensions Length: 36
                Extension: renegotiation_info (len=1)
                Extension: server_name (len=0)
                Extension: ec_point_formats (len=4)
                Extension: extended_master_secret (len=0)
                Extension: application_layer_protocol_negotiation (len=11)
        TLSv1.2 Record Layer: Handshake Protocol: Certificate
            Content Type: Handshake (22)
            Version: TLS 1.2 (0x0303)
            Length: 770
            Handshake Protocol: Certificate
                Handshake Type: Certificate (11)
                Length: 766
                Certificates Length: 763
                Certificates (763 bytes)
                    Certificate Length: 760
                    Certificate: 308202f4308201dca003020102020900fa9c5b27a0c1368d… (id-at-commonName=www.chrono.com)
                        signedCertificate
                        algorithmIdentifier (sha256WithRSAEncryption)
                        Padding: 0
                        encrypted: 6dd90318e47d1b41728f04802a85eedca00a615feed7a67f…
        TLSv1.2 Record Layer: Handshake Protocol: Server Key Exchange
            Content Type: Handshake (22)
            Version: TLS 1.2 (0x0303)
            Length: 300
            Handshake Protocol: Server Key Exchange
                Handshake Type: Server Key Exchange (12)
                Length: 296
                EC Diffie-Hellman Server Params
                    Curve Type: named_curve (0x03)
                    Named Curve: x25519 (0x001d)
                    Pubkey Length: 32
                    Pubkey: 780f25b44d2ebb5df7ead5e9b6b32c2d40bb7094f16ac7c6…
                    Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
                        Signature Hash Algorithm Hash: SHA512 (6)
                        Signature Hash Algorithm Signature: RSA (1)
                    Signature Length: 256
                    Signature: 6778592c6742cbd45ff120ce72d1a442a8c5cdbb65e792d5…
        TLSv1.2 Record Layer: Handshake Protocol: Server Hello Done
            Content Type: Handshake (22)
            Version: TLS 1.2 (0x0303)
            Length: 4
            Handshake Protocol: Server Hello Done
                Handshake Type: Server Hello Done (14)
                Length: 0
    
    
    

    然后,服务器为了证明自己的身份,就把证书也发给了客户端(Server Certificate)。

    接下来是一个关键的操作,因为服务器选择了 ECDHE 算法,所以它会在证书后发送“Server Key Exchange”消息,里面是椭圆曲线的公钥(Server Params),用来实现密钥交换算法,再加上自己的私钥签名认证

    TLSv1.2 Record Layer: Handshake Protocol: Server Key Exchange
            Content Type: Handshake (22)
            Version: TLS 1.2 (0x0303)
            Length: 300
            Handshake Protocol: Server Key Exchange
                Handshake Type: Server Key Exchange (12)
                Length: 296
                EC Diffie-Hellman Server Params
                    Curve Type: named_curve (0x03)
                    Named Curve: x25519 (0x001d)
                    Pubkey Length: 32
                    Pubkey: 780f25b44d2ebb5df7ead5e9b6b32c2d40bb7094f16ac7c6…
                    Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
                        Signature Hash Algorithm Hash: SHA512 (6)
                        Signature Hash Algorithm Signature: RSA (1)
                    Signature Length: 256
                    Signature: 6778592c6742cbd45ff120ce72d1a442a8c5cdbb65e792d5…
    
    • 1.指明自己使用的椭圆曲线(一般根据客户端的拓展中supported_groups中的选择椭圆曲线算法)

    • 2 服务器本地计算一个大数(BIGNUM),乘上曲线的base point,得到一个新的point,这个point就是公钥,用04+x+y的格式组织起来。04表示unconpressed point,和客户端的ec_point_formats有关。

    • 3 签名 。和RSA握手不同,RSA情况下, 只要能值正常协商密钥,那么必然服务器端有证书对应的私钥,也间接表明了服务器拥有该证书。
      DHE/ECDHE不同,证书对应的私钥并不参与密钥协商,如果要证明服务器拥有证书,则必然有签名的操作(就像双向认证的情况下,客户端需要发送certificate verify)。
      被签名数据从curve type起,至point的y为止。
      对于TLS1.2,签名算法使用client hello拓展中提供的摘要算法;TLS1.0和TLS1.1,如果本地证书是ECC证书,即若要使用ECDSA签名,这种摘要算法为SHA1,其他的情况摘要算法为md5+sha1。

    计算摘要之后就调用RSA或者ECDSA进行签名。注意的是,TLS1.2时报文要带上2字节的“Signature Hash Algorithm”,如上图高亮部分,这是TLS1.2协议相较于之前协议不同之处之一,但是这2部分不参与签名计算

    这相当于说:“刚才我选的密码套件有点复杂,所以再给你个算法的参数,和刚才的随机数一样有用,别丢了。为了防止别人冒充,我又盖了个章。

    ”之后是“Server Hello Done”消息,服务器说:“我的信息就是这些,打招呼完毕。”这样第一个消息往返就结束了(两个 TCP 包),结果是客户端和服务器通过明文共享了三个信息:Client Random、Server Random 和 Server Params。

    客户端这时也拿到了服务器的证书,那这个证书是不是真实有效的呢?
    开始走证书链逐级验证,确认证书的真实性,再用证书公钥验证签名,就确认了服务器的身份:“刚才跟我打招呼的不是骗子,可以接着往下走。”然后,客户端按照密码套件的要求,也生成一个椭圆曲线的公钥(Client Params),用“Client Key Exchange”消息发给服务器。

    Handshake Protocol: Client Key Exchange
        EC Diffie-Hellman Client Params
            Pubkey: 8c674d0e08dc27b5eaa…
    

    现在客户端和服务器手里都拿到了密钥交换算法的两个参数(Client Params、Server Params),就用 ECDHE 算法一阵算,算出了一个新的东西,叫“Pre-Master”,其实也是一个随机数。

    至于具体的计算原理和过程,因为太复杂就不细说了,但算法可以保证即使黑客截获了之前的参数,也是绝对算不出这个随机数的。

    现在客户端和服务器手里有了三个随机数:Client Random、Server Random 和 Pre-Master。
    用这三个作为原始材料,就可以生成用于加密会话的主密钥,叫“Master Secret”。而黑客因为拿不到“Pre-Master”,所以也就得不到主密钥。为什么非得这么麻烦,非要三个随机数呢?

    这就必须说 TLS 的设计者考虑得非常周到了,他们不信任客户端或服务器伪随机数的可靠性,为了保证真正的“完全随机”“不可预测”,把三个不可靠的随机数混合起来,那么“随机”的程度就非常高了,足够让黑客难以猜测。

    master_secret = PRF(pre_master_secret, "master secret",
                        ClientHello.random + ServerHello.random)
    

    这里的“PRF”就是伪随机数函数,它基于密码套件里的最后一个参数,比如这次的 SHA384,通过摘要算法来再一次强化“Master Secret”的随机性。

    主密钥有 48 字节,但它也不是最终用于通信的会话密钥,还会再用 PRF 扩展出更多的密钥,比如客户端发送用的会话密钥(client_write_key)、服务器发送用的会话密钥(server_write_key)等等,避免只用一个密钥带来的安全隐患。

    有了主密钥和派生的会话密钥,握手就快结束了。客户端发一个“Change Cipher Spec”,然后再发一个“Finished”消息,把之前所有发送的数据做个摘要,再加密一下,让服务器做个验证。

    意思就是告诉服务器:“后面都改用对称算法加密通信了啊,用的就是打招呼时说的 AES,加密对不对还得你测一下。

    ”服务器也是同样的操作,发“Change Cipher Spec”和“Finished”消息,双方都验证加密解密 OK,握手正式结束,后面就收发被加密的 HTTP 请求和响应了

    • HTTPS 协议会先与服务器执行 TCP 握手,然后执行 TLS 握手,才能建立安全连接
    • 握手的目标是安全地交换对称密钥,需要三个随机数,第三个随机数“Pre-Master”必须加密传输,绝对不能让黑客破解;
    • “Hello”消息交换随机数,“Key Exchange”消息交换“Pre-Master”;
    • “Change Cipher Spec”之前传输的都是明文,之后都是对称密钥加密的密文

    TLS协议组成

    记录协议

    Record Protocol ,规定了TLS收发数据的基本单位。它有点类似TCP里的segment,所有的其它子协议都需要通过记录协议发出
    但是多个记录数据可以在1个TCP包里一次性发出,也并不需要像TCP那样返回ACK

    警报协议

    Alert protocol 职责是向对方发出警报信息,类似http协议里的状态码。
    比如protocol_version 就死不支持旧版本 bad_certificate就是证书有问题
    收到警报后,另一方可以选择终止连接,也可以选择继续

    握手协议

    (Handshake Protocol)是 TLS 里最复杂的子协议,要比 TCP 的 SYN/ACK 复杂的多,浏览器和服务器会在握手过程中协商

    • TLS 版本号、
    • 随机数、
    • 密码套件等信息,

    然后交换证书和密钥参数,最终双方协商得到会话密钥,用于后续的混合加密系统

    变更密码规范协议

    (Change Cipher Spec Protocol),它非常简单,就是一个“通知”,告诉对方,后续的数据都将使用加密保护。那么反过来,在它之前,数据都是明文的

    第一阶段:C/S两端共享Client Random、Server Random 和 Server Params信息
    客户端--->服务器:
    客户端的版本号、支持的密码套件,还有一个随机数(Client Random)
    
    服务端--->客户端:
    客户端的版本号、选择的客户端列表的密码套件如:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384、随机数随机数(Server Random)
    
    服务端--->客户端:
    服务端证书(Server Certificate)
    
    
    服务端--->客户端:
    发送Server Key Exchange类型的请求,携带椭圆曲线的公钥(Server Params)用以实现密钥交换算法,另附私钥签名
    
    
    服务端--->客户端:
    发送完毕
    
    
    第二阶段:证书验证
    
    前验条件:客户端证书链逐级验证、证书公钥验证签名,服务端身份验证成功(证书合法)
    
    客户端--->服务端
    发送Client Key Exchange类型的请求,携带椭圆曲线的公钥(Client Params)用以实现秘钥交换算法
    
    
    第三阶段:主密钥生成
    
    客户端、服务端分别使用Client Params、Server Params通过ECDHE算法计算出随机值pre-master,然后用
    Client Random、Server Random 和 Pre-Master三个值作为原材料,用PRF伪随机数函数(利用密码套件的摘要算法再次强化结果
    值maser secert的随机性)计算出主密钥Master Secret,
    
    主密钥并不是会话秘钥,还会再用PRF扩展出更多的密钥,比如客户端发送用的会话密钥(client_write_key)、服务器发送用的会话密钥(server_write_key)
    
    
    客户端--->服务端:
    客户端发一个“Change Cipher Spec”,然后再发一个“Finished”消息,把之前所有发送的数据做个摘要,再加密一下,让服务器做个验证.
    
    服务端--->客户端:
    服务器也是同样的操作,发“Change Cipher Spec”和“Finished”消息,双方都验证加密解密 OK,握手正式结束.
    
    

    1.client hello 【client->server】

    • client发送 随机数randomC,tls版本,支持的密码套件,扩展信息到服务端

    2.server hello 【server-client】

    • server 发送 随机数randomS,tls版本确认,选择的密码套件,扩展信息到client

    3.certificate 【server->client】

    4.server key exchange 【server->client】

    • EC Diffie-Hellman Server Params
      • Curve Type(曲线类型)
      • Pubkey
      • Signature Algorithm和Signature

    5.server hello done 【server ->client】

    https://blog.csdn.net/mrpre/article/details/78025940

  • 相关阅读:
    LINQ to SQL活学活用(2):躲起来别让我看见
    UTF8的問題
    简单的appendChild示例
    LINQ to SQL活学活用(4):监视你的一举一动
    LinQ中的SortBy+sum+count的用法
    ajax的问题
    [综] Canny Edge Detection 代码
    [转] 图像处理中的拉普拉斯算子
    [ZZ] SCI 投稿全过程信件模板一览
    [转] MATLAB图像实用源代码
  • 原文地址:https://www.cnblogs.com/HKUI/p/13866663.html
Copyright © 2011-2022 走看看