TLS握手及其报文具体分析,服务器视角

一给  金牌会员 | 2024-7-30 23:00:57 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 541|帖子 541|积分 1623

1、客户端的Client Hello开始

发送此消息的时间:

当客户端首次连接到服务器时,它必须发送ClientHello作为其第一条消息。客户端还可以响应HelloRequest消息或自动发送ClientHello消息以重新协商现有连接中的安全参数。
记载层1字节2字节3字节4字节5字节
Content Type: HandshakeVersion: TLS 1.2Length
0x220x0303---
握手层Handshake Type: Client Hello LengthVersion: TLS 1.2 
0x010x0303
Version: TLS 1.2Random: (GMT Unix Time: Jun 26, 2024 11:04:47.000000000 中国标定时间)
0x0303
Random: (Random Bytes)
Random: (Random Bytes)
Random: (Random Bytes)
Random: (Random Bytes)
Random: (Random Bytes)
Random: (Random Bytes)Session ID Length: 0
接着上面就是密钥,压缩算法
Cipher Suites Length: 208Cipher Suites Length: 208(密钥长度)Cipher Suites (104 suites)(密钥)
Compression Methods Length: 1(压缩算法长度)Compression Methods (1 method)(压缩算法)
Extensions Length: 80(扩展长度)Extensions (扩展)

接下来我们用python进行组包
  1. from scapy.all import *
  2. from collections import namedtuple
  3. from scapy.layers.tls.all import *
  4. from scapy.layers.inet import *
  5. iface = namedtuple('iface', 'name ip port')
  6. ETH_IFACE_A = iface(name='VMware Network Adapter VMnet8', ip='192.168.138.1', port=4233)
  7. ETH_IFACE_B = iface(name='VMware Network Adapter VMnet8', ip='192.168.138.129', port=4433)
  8. # 创建TLS HelloRequest消息
  9. tls_ClientHello =TLS(type=22,version=0x0303,msg=TLSClientHello(version="TLS 1.2"))
  10. tls_ClientHello.show()
  11. sip = Ether() / IP(src=ETH_IFACE_A.ip, dst=ETH_IFACE_B.ip) / TCP(sport=ETH_IFACE_A.port,
  12.                                                            dport=ETH_IFACE_B.port)/tls_ClientHello
  13. sendp(sip, iface=ETH_IFACE_A.name)
  14. print(sip.build())
复制代码
具体可以看以下抓包

在发送ClientHello消息后,客户端等候ServerHello消息。服务器返回的任何握手消息,除了HelloRequest,都将被视为致命错误。
2、Server Hello

发送此消息的时间:

服务器在能够找到一组可接受的算法后,将响应ClientHello消息并发送此消息。假如找不到匹配的算法,服务器将以握手失败警报作为回应。
记载层1字节2字节3字节4字节
Content Type: HandshakeVersion: TLS 1.2Length
0x220x0303---
握手层Handshake Type: servert Hello Length
0x02
Version: TLS 1.2Random: (GMT Unix Time: Jun 26, 2024 11:04:47.000000000 中国标定时间)
0x0303
Random: (Random Bytes)
Random: (Random Bytes)
Random: (Random Bytes)
Random: (Random Bytes)
Random: (Random Bytes)
Random: (Random Bytes)

Session ID LengthSession ID
Cipher Suites (两个字节)Compression Methods 

同样打开mbedtls客户端,应用scapy组包发送,抓包如下。

发包的时间注意,压缩算法和密钥必须是cllienthello里面,不然就会错误。


3、Server Certificate

发送时机:

当约定的密钥互换方法利用证书进行身份验证时(本文件定义的所有密钥互换方法除DH_anon外),服务器必须发送证书消息。此消息总是紧跟在ServerHello消息之后。
消息意义:

此消息将服务器的证书链转达给客户端。证书必须恰当协商的密码套件的密钥互换算法和任何协商的扩展。
客户端响应服务器的证书哀求消息时将利用相同的消息范例和布局。注意,假如客户端没有合适的证书来响应服务器的身份验证哀求,它可能不发送任何证书。
服务器发送的证书的规则:



  • 证书范例必须是X.509v3,除非明白协商了其他范例(例如,TLSPGP)。
  • 终端实体证书的公钥(及相干限定)必须与所选密钥互换算法兼容。

  • 假如客户端提供了signature_algorithms扩展,则服务器提供的所有证书必须由该扩展中出现的哈希/签名算法对签名。这意味着一个包含某个签名算法密钥的证书可以由差别签名算法签名(例如,利用DSA密钥签名的RSA密钥)。这与TLS 1.1要求算法相同的规定有所差别。
    假如服务器有多个证书,它会根据上述标准(以及其他标准,例如传输层端点、本地配置和偏好等)选择一个。假如服务器只有一个证书,它应实验验证该证书是否符合这些标准。
    注意,有些证书利用的算法和/或算法组合目前不能用于TLS。例如,带有RSASSA-PSS签名密钥的证书(在SubjectPublicKeyInfo中为id-RSASSA-PSS OID)不能利用,因为TLS没有定义相应的签名算法。
    随着为TLS协议指定新密钥互换方法的密码套件的引入,它们将暗示证书格式和所需的编码密钥信息。
  •    
    记载层1字节2字节3字节4字节
    Content Type: HandshakeVersion: TLS 1.2Length
    0x220x0303---
    握手层Handshake TypeLength
    Certificate LengthCertificate Length

  • 证书先在openssl上进行天生然后进行导入,同样打开mbedtls客户端,我们发送证书。


  • 4、Server Key Exchange Message
  • 发送此消息的时间: 当服务器证书消息(假如发送)或ServerHello消息(假如这是匿名协商)中不包含足够的数据,使得客户端无法互换预主密钥时,服务器将立即发送此消息。
    消息的含义: 此消息转达加密信息,以便客户端能够天生预主密钥:包罗一个Diffie-Hellman公钥,客户端可以用它完成密钥互换(天生预主密钥),大概其他算法的公钥。
  • enum {
        dhe_dss, dhe_rsa, dh_anon, rsa, dh_dss, dh_rsa
        /* 可能会扩展,例如对于ECDH,请参阅[TLSECC] */
    } KeyExchangeAlgorithm;
    struct {
        opaque dh_p<1..2^16-1>;
        opaque dh_g<1..2^16-1>;
        opaque dh_Ys<1..2^16-1>;
    } ServerDHParams; /* 临时DH参数 */
    dh_p:
    用于Diffie-Hellman操纵的素数模数。
    dh_g:
    用于Diffie-Hellman操纵的天生器。
    dh_Ys:
    服务器的Diffie-Hellman公共值(g^X mod p)。
    struct {
        select (KeyExchangeAlgorithm) {
            case dh_anon:
                ServerDHParams params;
            case dhe_dss:
            case dhe_rsa:
                ServerDHParams params;
                digitally-signed struct {
                    opaque client_random[32];
                    opaque server_random[32];
                    ServerDHParams params;
                } signed_params;
            case rsa:
            case dh_dss:
            case dh_rsa:
                struct {};
                /* 对于rsa、dh_dss和dh_rsa,消息被省略 */
            /* 可能会扩展,例如对于ECDH,请参阅[TLSECC] */
        };
    } ServerKeyExchange;
  • params: 服务器的密钥互换参数。
    signed_params: 对于非匿名密钥互换,对服务器的密钥互换参数进行签名。
    假如客户端提供了"signature_algorithms"扩展,签名算法和哈希算法必须是该扩展中列出的一对。请注意,这里存在一些可能的不一致性。例如,客户端可能提供了DHE_DSS密钥互换,但在其"signature_algorithms"扩展中省略了任何DSA对。为了正确协商,服务器在选择任何候选密码套件之前,必须根据"signature_algorithms"扩展查抄其兼容性。只管这种方法不够优雅,但它是对原始密码套件设计的一种折衷方案。
    此外,哈希和签名算法必须与服务器端终端实体证书中的密钥兼容。RSA密钥可以利用任何允许的哈希算法,但受证书中的限定(假如有)的限定。
    由于DSA签名不包含任何安全的哈希算法指示,假如利用多个哈希算法与任何密钥一起利用,存在哈希更换的风险。当前,DSA [DSS] 只能与SHA-1一起利用。预计未来的DSS [DSS-3]修订版将允许在DSA中利用其他择要算法,并指导每个密钥大小应利用哪些择要算法。此外,未来的[PKIX]修订版可能会指定证书用于指示与DSA一起利用的择要算法的机制。
    随着为TLS定义包含新的密钥互换算法的其他密码套件,只有当与密钥互换算法相干联的证书范例不提供足够的信息以供客户端互换预主密钥时,才会发送服务器密钥互换消息。
  • 假如hello消息里面利用的是rsa则跳过这一步
  • 4、TLSCertificateRequest
  • ### 7.4.4. 证书哀求
    **发送此消息的时间**:
    非匿名服务器可以选择性地要求客户端提供证书,假如对所选密码套件合适的话。假如发送了服务器密钥互换消息,则此消息将紧随其后(否则,此消息将跟随服务器的证书消息)。
    **消息的布局**:
    ```plaintext
    enum {
        rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
        rsa_ephemeral_dh_RESERVED(5), dss_ephemeral_dh_RESERVED(6),
        fortezza_dms_RESERVED(20), (255)
    } ClientCertificateType;
    opaque DistinguishedName<1..2^16-1>;
    struct {
        ClientCertificateType certificate_types<1..2^8-1>;
        SignatureAndHashAlgorithm supported_signature_algorithms<2^16-1>;
        DistinguishedName certificate_authorities<0..2^16-1>;
    } CertificateRequest;
    ```
    **certificate_types**:
    客户端可以提供的证书范例列表。
    - rsa_sign:包含RSA密钥的证书。
    - dss_sign:包含DSA密钥的证书。
    - rsa_fixed_dh:包含静态DH密钥的证书。
    - dss_fixed_dh:包含静态DH密钥的证书。
    **supported_signature_algorithms**:
    服务器能够验证的哈希/签名算法对列表,按优先级降序分列。
    **certificate_authorities**:
    可接受的证书颁发机构的专著名单,以DER编码格式表示。这些专著名可以指定根CA或下级CA的期望专著名;因此,此消息可用于形貌已知根CA以及所需的授权空间。假如certificate_authorities列表为空,则客户端可以发送任何恰当ClientCertificateType的证书,除非有外部安排要求差别。
    证书范例和supported_signature_algorithms字段的交互有些复杂。certificate_types自SSLv3以来一直存在,但规范不敷。大部分功能已被supported_signature_algorithms取代。以下规则适用:
    - 客户端提供的任何证书必须利用supported_signature_algorithms中的哈希/签名算法对进行签名。
    - 客户端提供的终端实体证书必须包含与certificate_types兼容的密钥。假如密钥是签名密钥,则必须能够与supported_signature_algorithms中的某个哈希/签名算法对一起利用。
    - 由于汗青原因,某些客户端证书范例的名称包罗用于签名证书的算法。例如,在TLS较早版本中,rsa_fixed_dh表示利用RSA签名的静态DH密钥的证书。在TLS 1.2中,这种功能已被supported_signature_algorithms淘汰,并且证书范例不再限定用于签名证书的算法。例如,假如服务器发送dss_fixed_dh证书范例和{{sha1, dsa}, {sha1, rsa}}签名范例,客户端可以复兴利用RSA-SHA1签名的静态DH密钥的证书。
    新的ClientCertificateType值由IANA分配,详见第12节。
    **注意**:列为保留的值不得利用。它们在SSLv3中利用过。
    **注意**:匿名服务器哀求客户端认证是一个致命的握手失败警报。
  • 同样打开模拟客户端,抓包。




  • 5、Server Hello Done
  • ### 7.4.5. 服务器完成消息
    **发送此消息的时间**:
    服务器发送ServerHelloDone消息来指示ServerHello及相干消息的竣事。发送此消息后,服务器将等候客户端的响应。
    **消息的含义**:
    此消息表示服务器已经完成发送支持密钥互换所需的消息,客户端可以继续其密钥互换阶段。
    收到ServerHelloDone消息后,客户端**应**实行以下操纵:
    - 假如须要,验证服务器提供的有用证书。
    - 查抄服务器Hello参数是否可接受。
    **消息的布局**:
    ```plaintext
    struct { } ServerHelloDone;
    ```
    这是一个空布局体,表示服务器没有额外的数据须要发送,并且希望客户端继续密钥互换过程。
  •    
    记载层1字节
    Content Type: Handshakeversion
    0x22
    握手层Handshake Typeversion
    server hello donelenth




  • 7、客户端后续


  • 8、 Change Cipher Spec

  • 发送时机:
    Change Cipher Spec消息由TLS服务器发送,用于指示其已经完成密钥互换,并准备好开始利用新密钥加密通讯数据。此消息是TLS协议中的一部分,用于确保在通讯过程中的数据保密性和完整性。


  • 9、finish


    ### Finished 消息
    #### 发送时机:
    Finished 消息总是在变更密码规范消息之后立即发送,以验证密钥互换和认证过程是否乐成。在发送 Finished 消息之前,必须吸收到其他握手消息和变更密码规范消息。
    #### 意义:
    Finished 消息是利用刚刚协商好的算法、密钥和秘密进行掩护的第一个消息。吸收者必须验证其内容是否正确。一旦一方发送了自己的 Finished 消息并吸收并验证了对等方的 Finished 消息,就可以开始在连接上发送和吸收应用程序数据。
    #### 消息布局:
    ```c
    struct {
        opaque verify_data[verify_data_length];
    } Finished;
    ```
    - `verify_data`:验证数据,其长度取决于密码套件的具体定义。
    - `finished_label`:对于客户端发送的 Finished 消息,字符串为 "client finished"。对于服务器发送的 Finished 消息,字符串为 "server finished"。
    - `Hash(handshake_messages)`:握手消息的哈希值,用作 PRF 函数的输入。
    在之前的TLS版本中,`verify_data` 总是12个八位字节长。在当前版本中,它依靠于密码套件的定义。假如密码套件未显式指定 `verify_data` 的长度,则其长度为12个字节。这适用于所有现有的密码套件。未来的密码套件可以指定其他长度,但长度必须至少为12字节。
    #### 握手消息:
    `handshake_messages` 包罗握手过程中所有消息的数据(不包罗任何 HelloRequest 消息),直到但不包罗该 Finished 消息。这是握手层可见的所有数据,不包罗记载层头部。这是在握手过程中互换的所有 Handshake 布局的串联。
    假如 Finished 消息在握手过程中没有在恰当的时间点之前由 ChangeCipherSpec 消息前导,则会导致致命错误。
    注意:ChangeCipherSpec 消息、警报和任何其他记载范例不是握手消息,因此不包罗在哈希计算中。


  •   好了一套流程下来了,废了我半条命,不想写了

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

一给

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表