欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TLS1.3---**的计算

程序员文章站 2022-07-12 22:03:29
...

TLS1.2中的PRF

通过对TLS1.2的学习,我了解到其中具有三种**:预主**、主**和会话**。
在其握手过程中,客户端和服务器都会根据密码套件生成自己的临时公私钥对,并且将公钥发送给对方,当客户端接收到服务器的公钥时,会生成预主**。
之后客户端会使用PRF函数计算出主**发送给服务器,计算时需要三个输入:

  • 预主**
  • 客户端生成的随机数
  • 服务器生成的随机数

如果使用的是RSA,那么预主**的结构如下:

    struct {
             uint32 gmt_unix_time;
             opaque random_bytes[28];
         } Random;
         
        struct {
             ProtocolVersion client_version;
             opaque random[46];
         } PreMasterSecret;  

        struct {
             uint8 major;
             uint8 minor;
         } ProtocolVersion;   

会话**也是通过PRF函数生成的,需要输入:

  • 主**
  • 客户端生成的随机数
  • 服务器生成的随机数

Session ID 缓存和 Session Ticket 里面保存的也是主**,而不是会话**,这样每次会话复用的时候再用双方的随机数和主**导出会话**,从而实现每次加密通信的会话**不一样,即使一个会话的主**泄露了或者被**了也不会影响到另一个会话。

P_HASH算法

它使用一个 hash 函数扩展成一个 secret 和种子,形成任意大小的输出。其中的哈希函数取决于协商的密码套件。

P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
                             HMAC_hash(secret, A(2) + seed) +
                             HMAC_hash(secret, A(3) + seed) + ...

其中的A():

    A(0) = seed
    A(i) = HMAC_hash(secret, A(i-1))

"+"表示连接,HMAC_hash的运算次数取决于想要结果的长度。
在计算不同类型的**时,对应的secret值也是不同的

HKDF

通过前面的介绍,我们已经大概了解了TLS1.2中的**生成实现过程,在TLS1.3中主要使用的是HKDF中的 HKDF-Extract 和 HKDF-Expand 函数,HKDF的主要的目标是获取一些初始的**材料,并从中派生出一个或多个安全强度很大的**。主要分为两步:

提取

HKDF-Extract(salt, IKM) -> PRK

使用协商好的哈希算法将输入的**尽量的伪随机化。

  • Salt:输入,如果不提供则全部初始化为0的字符串,长度则为所采用哈希函数的散列值长度。
  • IKM:输入,**材料,在TLS1.3中比较复杂。
  • PRK:输出,伪随机化后的**,长度则为所采用哈希函数的散列值长度。

扩展

通过一系列的哈希运算,将**扩展到我们所需要的长度,有点类似TLS1.2中的P_HASH。

HKDF-Expand(PRK,info,L)-> OKM 
  • info:可选上下文和应用程序特定信息(可以是零长度字符串),我们可以理解为要计算**的名称。
  • L:所需要的长度。
  • OKM:计算得出的**结果

下面看一下OKM的计算方式:

   N = ceil(L / HashLen)
   T = T(1| T(2| T(3| ... | T(N)
   OKM = T的前L个八位位组,

   其中:
   T(0= 空字符串(零长度)
   T(1= HMAC-Hash(PRK,T(0| info | 0x01)
   T(2= HMAC-Hash(PRK,T(1| info | 0x02 )
   T(3= HMAC-Hash(PRK,T(2| info | 0x03... 

   (其中,连接到每个T(n)末尾的常数是一个
   八位位组。)

n为0-255的整数,L除以所用哈希函数输出摘要的长度,再向上取整,我们将其记为n。
然后将T(n)串接起来,而我们想要获得的OKM正是取T的前L个字节组成。这要我们就得到了我们想要的**材料。

TLS1.3**计算

 HKDF-Expand-Label(Secret, Label, Context, Length) =
            HKDF-Expand(Secret, HkdfLabel, Length)

       Where HkdfLabel is specified as:

       struct {
           uint16 length = Length;
           opaque label<7..255> = "tls13 " + Label;
           opaque context<0..255> = Context;
       } HkdfLabel;

       Derive-Secret(Secret, Label, Messages) =
            HKDF-Expand-Label(Secret, Label,
                              Transcript-Hash(Messages), Hash.length)

Transcript-Hash 和 HKDF 使用的 Hash 函数是密码套件哈希算法,Hash.length 是其输出长度(以字节为单位)。消息是表示的握手消息的串联,包括握手消息类型和长度字段,但不包括记录层头,labels 都是 ASCII 字符串。

TLS 1.3 完整的**导出流程图

  0
             |
             v
   PSK ->  HKDF-Extract = Early Secret
             |
             +-----> Derive-Secret(., "ext binder" | "res binder", "")
             |                     = binder_key
             |
             +-----> Derive-Secret(., "c e traffic", ClientHello)
             |                     = client_early_traffic_secret
             |
             +-----> Derive-Secret(., "e exp master", ClientHello)
             |                     = early_exporter_master_secret
             v
       Derive-Secret(., "derived", "")
             |
             v
   (EC)DHE -> HKDF-Extract = Handshake Secret
             |
             +-----> Derive-Secret(., "c hs traffic",
             |                     ClientHello...ServerHello)
             |                     = client_handshake_traffic_secret
             |
             +-----> Derive-Secret(., "s hs traffic",
             |                     ClientHello...ServerHello)
             |                     = server_handshake_traffic_secret
             v
       Derive-Secret(., "derived", "")
             |
             v
   0 -> HKDF-Extract = Master Secret
             |
             +-----> Derive-Secret(., "c ap traffic",
             |                     ClientHello...server Finished)
             |                     = client_application_traffic_secret_0
             |
             +-----> Derive-Secret(., "s ap traffic",
             |                     ClientHello...server Finished)
             |                     = server_application_traffic_secret_0
             |
             +-----> Derive-Secret(., "exp master",
             |                     ClientHello...server Finished)
             |                     = exporter_master_secret
             |
             +-----> Derive-Secret(., "res master",
                                   ClientHello...client Finished)
                                   = resumption_master_secret
相关标签: TLS/SSL tls