TLS1.3 和 TLS1.2 证书等消息的不同

2019-02-01 17:34:13 +08:00
 hxndg

打算简单说下三个方面:证书消息,证书请求消息,证书 verify 消息。

证书消息

TLS1.3 和 TLS1.2 版本的证书消息本质上差别不大,还是老的消息发出来,格式基本一致。主要不同的是 TLS1.2 中的证书链是一个证书跟着一个证书的,也就是一个 cert entry 跟着另一个 cert entry,每一个 cert entry 验证下一个 cert entry。下面就是 TLS1.2 当中的证书结构,这里 ASN.1Cert 就是一个 cert entry,每个都是标准的 X.509v3 结构

opaque ASN.1Cert<1..2^24-1>;
      struct {
          ASN.1Cert certificate_list<0..2^24-1>;
      } Certificate;

而 TLS1.3 中的 certificate 消息现包含一个 certificate request context,这个字段是应对于 certificate request 中的 certificate request context,提供一次保护性的。对于服务端而言他没收到 certificate request,自然这个字段长度为 0. 另外一点是 TLS1.3 中证书 list 包含的单条证书被拓展隔开了,格式变成了每一个证书后面都有一个拓展字段,隔开下一条证书。

struct {
          select (certificate_type) {
              case RawPublicKey:
                /* From RFC 7250 ASN.1_subjectPublicKeyInfo */
                opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;

              case X509:
                opaque cert_data<1..2^24-1>;
          };
          Extension extensions<0..2^16-1>;
      } CertificateEntry;

目前服务端拓展只支持两种 OCSP Status   extension [RFC6066] 和 SignedCertificateTimestamp extension[RFC6962],服务端证书当中的拓展必须和 ClientHello 报文的拓展对应,而客户端证书的拓展也必须和 CertificateRequest 证书当中的保持一致。当然 ustack 系统中目前不需要考虑这些。

最后一点变化是目前整数类型可以为 RawPublicKey,但是一般情况下在 EE 报文中并不会特意协商类型为 RawPublicKey,也就是不会在 server_certificate_type 拓展中协商为 RawPublicKey 所以一般格式还是 X.509v3 的标准证书格式。上面的 cert_data 就是原先的 ASN.1Cert

证书请求消息

功能上 certificate request 消息并没有变化,还是请求客户端证书的作用。 但是 TLS1.2 中结构复杂,结构为

struct {
          ClientCertificateType certificate_types<1..2^8-1>;
          SignatureAndHashAlgorithm
            supported_signature_algorithms<2^16-1>;
          DistinguishedName certificate_authorities<0..2^16-1>;
      } CertificateRequest;

TLS1.3 中,结构稍微简化为:

struct {
          opaque certificate_request_context<0..2^8-1>;
          Extension extensions<2..2^16-1>;
      } CertificateRequest;

certificate_request_context 根据报文种类变化,如果是 PHA 报文,那么生产长度为 32 的随机数据填充。如果不是 PHA 报文,那么长度为 0.extensions 字段则包括了过去的 signature_algorithms 和 DistinguishedName 字段,从而使结构更加清楚。

证书 verify 消息

TLS1.3 Certificate Verify 用来证明发送的证书属于发送方,并保护前面发送的数据的完整性。TLS1.2 只用 Certificate Verify 消息来验证客户端证书的完整性. TLS1.3 中,这条消息必须紧贴 certificate message,且在 finish 之前。

TLS1.3 中这条消息如何计算?首选需要计算计算的主体:主体计算方式为: Transcript-Hash(Handshake Context, Certificate), 主体计算完成之后需要如下信息拼接到一起:

   - 重复 64 遍的 0x20 字符串 
   - 不同的环境标签,对于服务端是"TLS 1.3, server CertificateVerify"。对客户端是"TLS 1.3, client CertificateVerify"
   - 一个单 byte 的 0,拓展到报文里实际上是个 0x00
   - 上面计算出来的主体

拼接到一起之后,利用和刚才发送的证书相关的签名秘钥进行计算。

TLS1.2 中这的 certificate verify 只给客户用,所以我们实际上需要对应 Server key exchange 消息,但是被签名出来的消息是:

     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 {} ;
                 /* message is omitted for rsa, dh_dss, and dh_rsa */
              /* may be extended, e.g., for ECDH -- see [TLSECC] */
          };
      } ServerKeyExchange;

拼接完成之后就可以计算签名。

如果实在好奇可以找我要这些网络抓包和秘钥文件,方便学习。我实在是懒得再截图啥的了。

嗯,再次宣传我司 ArrayNetworks 公司,性能好,价格低 LUL

2693 次点击
所在节点    SSL
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/532504

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX