TLS 1.3 中的密钥派生过程
字数 2594 2025-10-28 08:36:45

好的,我们这次来学习一个非常重要且实用的算法:TLS 1.3 中的密钥派生过程

题目描述

在 TLS 1.3 协议中,通信双方(例如,你的浏览器和网站服务器)在完成了最初的“握手”并交换了一些公开参数后,需要生成一系列用于后续通信的加密密钥。这些密钥包括:

  • 用于加密通信数据的对称密钥(如 AES 密钥)。
  • 用于计算消息完整性验证码(MAC)的密钥

这个题目要求我们理解并解释 TLS 1.3 是如何从一个共享的秘密(Pre-Master Secret)开始,像一棵大树的树根一样,安全地“生长”出所有需要的密钥(各个树枝和树叶)的。这个过程的核心就是密钥派生

解题过程

我们将循序渐进地分解这个过程。

步骤一:建立基础——获得“种子”

在 TLS 1.3 中,密钥派生的起点是一个被称为 “早期秘密(Early Secret)” 的数值。这个早期秘密的生成方式比较复杂,但为了简化理解,你可以把它想象成通信双方通过密钥交换算法(如 ECDHE)计算出的一个只有他们两方知道的、高熵的、随机的共享秘密。我们称之为 “初始种子”

关键点:这个初始种子是后续所有密钥的“根”,必须绝对保密。

步骤二:引入“神奇的生长配方”——HKDF 算法

TLS 1.3 的密钥派生过程依赖于一个标准化的算法,叫做 HKDF。你可以把 HKDF 想象成一个非常安全且灵活的“密钥生长机”。它需要三个“原料”:

  1. 输入密钥材料(IKM):这就是我们的“种子”,也就是上一步的早期秘密。
  2. 盐(Salt):可以理解为一种“调味料”,增加随机性。在 TLS 1.3 的首次派生中,盐通常是一串固定的零或其他预定义值。
  3. 信息(Info):这是一个非常重要的“标签”。它就像是一个生长指令,告诉 HKDF 机器:“我现在要生成的是用于客户端到服务器方向的加密密钥”。不同的 Info 会产出完全不同的密钥,这确保了密钥的独立性。

HKDF 内部主要分为两个阶段,我们用一个比喻来理解:

  • HKDF-Extract(提取阶段):将“种子”(IKM)和“盐”(Salt)混合,提取出一个更均匀、更随机的“主种子”,称为 PRK

    • PRK = HKDF-Extract(Salt, IKM)
    • 比喻:就像把原始种子和营养土(盐)混合,得到一块质地均匀的优质培养土(PRK)。
  • HKDF-Expand(扩展阶段):利用“主种子”(PRK)和特定的“生长指令”(Info),生长出指定长度的密钥材料。

    • OKM = HKDF-Expand(PRK, Info, L)
    • 比喻:从优质培养土(PRK)中,根据“长苹果”(Info=“苹果”)的指令,长出一个苹果(OKM=客户端加密密钥);根据“长橘子”(Info=“橘子”)的指令,长出一个橘子(OKM=服务器加密密钥)。L 指定了要长出多大的果实。

步骤三:构建密钥树——分层派生

TLS 1.3 的密钥派生不是一步到位的,而是分层的,像一棵树一样生长。这个过程被称为 密钥计划

  1. 从“早期秘密”到“握手秘密”

    • 将“早期秘密”作为 IKM,通过 HKDF-Extract 混合一个盐(来自服务器Hello消息的随机数),得到 “握手秘密”
    • 握手秘密 = HKDF-Extract(服务器Hello随机数, 早期秘密)
  2. 从“握手秘密”派生“握手阶段”使用的密钥

    • 现在,我们有了新的主种子——“握手秘密”。
    • 我们使用 HKDF-Expand,并搭配不同的 Info 标签,来生成握手阶段临时使用的密钥:
      • 客户端握手加密密钥 = HKDF-Expand(握手秘密, "client handshake key", 长度)
      • 服务器握手加密密钥 = HKDF-Expand(握手秘密, "server handshake key", 长度)
      • 客户端握手IV = HKDF-Expand(握手秘密, "client handshake iv", 长度) (IV是加密算法需要的初始向量)
      • 服务器握手IV = HKDF-Expand(握手秘密, "server handshake iv", 长度)
    • 作用:这些密钥被用来加密握手阶段最后几条“Finished”消息,验证握手过程是否被篡改。
  3. 从“握手秘密”到“主秘密”

    • 握手完成后,双方再使用 HKDF-Extract,将“握手秘密”与一个由双方握手消息计算出的哈希值(作为新的盐)混合,得到最终的 “主秘密”
    • 主秘密 = HKDF-Extract(握手消息哈希值, 握手秘密)
    • 目的:这实现了“前向安全”。即使有人后来破解了“握手秘密”,也无法计算出“主秘密”,因为破解者没有观察到完整的握手通信流(无法计算出正确的握手消息哈希值)。
  4. 从“主秘密”派生“应用数据”使用的密钥

    • “主秘密”是整个密钥树的最终根。用它来派生应用数据传输阶段的所有密钥。
    • 同样使用 HKDF-Expand 和不同的 Info 标签:
      • 客户端应用数据加密密钥 = HKDF-Expand(主秘密, "client application traffic key", 长度)
      • 服务器应用数据加密密钥 = HKDF-Expand(主秘密, "server application traffic key", 长度)
      • 客户端应用数据IV = HKDF-Expand(主秘密, "client application traffic iv", 长度)
      • 服务器应用数据IV = HKDF-Expand(主秘密, "server application traffic iv", 长度)

步骤四:总结与核心优势

整个过程可以可视化为一棵树:

               早期秘密 (种子)
                    |
              HKDF-Extract (盐: 服务器随机数)
                    |
               握手秘密 (树根)
               /         \
HKDF-Expand  ...        ...  HKDF-Expand
    /                   \
[握手密钥]          HKDF-Extract (盐: 握手消息哈希)
                         |
                     主秘密 (新树根)
                    /         \
         HKDF-Expand         HKDF-Expand
           /                       \
[客户端应用密钥]             [服务器应用密钥]

TLS 1.3 密钥派生的核心优势

  • 密钥分离:每个用途(握手加密、应用数据加密、客户端到服务器、服务器到客户端)都有独立的密钥,互不影响。
  • 前向安全:通过引入握手消息的哈希值来生成主秘密,确保了即使长期密钥泄露,过去的通信会话也无法被解密。
  • 灵活性:HKDF 算法可以方便地扩展出任意数量和长度的密钥。

通过这个循序渐进的过程,TLS 1.3 安全、可靠地从一个小小的共享秘密,构建出了保护我们整个互联网通信安全的加密密钥体系。

好的,我们这次来学习一个非常重要且实用的算法: TLS 1.3 中的密钥派生过程 。 题目描述 在 TLS 1.3 协议中,通信双方(例如,你的浏览器和网站服务器)在完成了最初的“握手”并交换了一些公开参数后,需要生成一系列用于后续通信的加密密钥。这些密钥包括: 用于加密通信数据的对称密钥 (如 AES 密钥)。 用于计算消息完整性验证码(MAC)的密钥 。 这个题目要求我们理解并解释 TLS 1.3 是如何从一个共享的秘密(Pre-Master Secret)开始,像一棵大树的树根一样,安全地“生长”出所有需要的密钥(各个树枝和树叶)的。这个过程的核心就是 密钥派生 。 解题过程 我们将循序渐进地分解这个过程。 步骤一:建立基础——获得“种子” 在 TLS 1.3 中,密钥派生的起点是一个被称为 “早期秘密(Early Secret)” 的数值。这个早期秘密的生成方式比较复杂,但为了简化理解,你可以把它想象成通信双方通过密钥交换算法(如 ECDHE)计算出的一个只有他们两方知道的、高熵的、随机的共享秘密。我们称之为 “初始种子” 。 关键点 :这个初始种子是后续所有密钥的“根”,必须绝对保密。 步骤二:引入“神奇的生长配方”——HKDF 算法 TLS 1.3 的密钥派生过程依赖于一个标准化的算法,叫做 HKDF 。你可以把 HKDF 想象成一个非常安全且灵活的“密钥生长机”。它需要三个“原料”: 输入密钥材料(IKM) :这就是我们的“种子”,也就是上一步的早期秘密。 盐(Salt) :可以理解为一种“调味料”,增加随机性。在 TLS 1.3 的首次派生中,盐通常是一串固定的零或其他预定义值。 信息(Info) :这是一个非常重要的“标签”。它就像是一个生长指令,告诉 HKDF 机器:“我现在要生成的是用于客户端到服务器方向的加密密钥”。不同的 Info 会产出完全不同的密钥,这确保了密钥的独立性。 HKDF 内部主要分为两个阶段,我们用一个比喻来理解: HKDF-Extract(提取阶段) :将“种子”(IKM)和“盐”(Salt)混合,提取出一个更均匀、更随机的“主种子”,称为 PRK 。 PRK = HKDF-Extract(Salt, IKM) 比喻 :就像把原始种子和营养土(盐)混合,得到一块质地均匀的优质培养土(PRK)。 HKDF-Expand(扩展阶段) :利用“主种子”(PRK)和特定的“生长指令”(Info),生长出指定长度的密钥材料。 OKM = HKDF-Expand(PRK, Info, L) 比喻 :从优质培养土(PRK)中,根据“长苹果”(Info=“苹果”)的指令,长出一个苹果(OKM=客户端加密密钥);根据“长橘子”(Info=“橘子”)的指令,长出一个橘子(OKM=服务器加密密钥)。 L 指定了要长出多大的果实。 步骤三:构建密钥树——分层派生 TLS 1.3 的密钥派生不是一步到位的,而是分层的,像一棵树一样生长。这个过程被称为 密钥计划 。 从“早期秘密”到“握手秘密” : 将“早期秘密”作为 IKM,通过 HKDF-Extract 混合一个盐(来自服务器Hello消息的随机数),得到 “握手秘密” 。 握手秘密 = HKDF-Extract(服务器Hello随机数, 早期秘密) 从“握手秘密”派生“握手阶段”使用的密钥 : 现在,我们有了新的主种子——“握手秘密”。 我们使用 HKDF-Expand,并搭配不同的 Info 标签,来生成握手阶段临时使用的密钥: 客户端握手加密密钥 = HKDF-Expand(握手秘密, "client handshake key", 长度) 服务器握手加密密钥 = HKDF-Expand(握手秘密, "server handshake key", 长度) 客户端握手IV = HKDF-Expand(握手秘密, "client handshake iv", 长度) (IV是加密算法需要的初始向量) 服务器握手IV = HKDF-Expand(握手秘密, "server handshake iv", 长度) 作用 :这些密钥被用来加密握手阶段最后几条“Finished”消息,验证握手过程是否被篡改。 从“握手秘密”到“主秘密” : 握手完成后,双方再使用 HKDF-Extract,将“握手秘密”与一个由双方握手消息计算出的哈希值(作为新的盐)混合,得到最终的 “主秘密” 。 主秘密 = HKDF-Extract(握手消息哈希值, 握手秘密) 目的 :这实现了“前向安全”。即使有人后来破解了“握手秘密”,也无法计算出“主秘密”,因为破解者没有观察到完整的握手通信流(无法计算出正确的握手消息哈希值)。 从“主秘密”派生“应用数据”使用的密钥 : “主秘密”是整个密钥树的最终根。用它来派生应用数据传输阶段的所有密钥。 同样使用 HKDF-Expand 和不同的 Info 标签: 客户端应用数据加密密钥 = HKDF-Expand(主秘密, "client application traffic key", 长度) 服务器应用数据加密密钥 = HKDF-Expand(主秘密, "server application traffic key", 长度) 客户端应用数据IV = HKDF-Expand(主秘密, "client application traffic iv", 长度) 服务器应用数据IV = HKDF-Expand(主秘密, "server application traffic iv", 长度) 步骤四:总结与核心优势 整个过程可以可视化为一棵树: TLS 1.3 密钥派生的核心优势 : 密钥分离 :每个用途(握手加密、应用数据加密、客户端到服务器、服务器到客户端)都有独立的密钥,互不影响。 前向安全 :通过引入握手消息的哈希值来生成主秘密,确保了即使长期密钥泄露,过去的通信会话也无法被解密。 灵活性 :HKDF 算法可以方便地扩展出任意数量和长度的密钥。 通过这个循序渐进的过程,TLS 1.3 安全、可靠地从一个小小的共享秘密,构建出了保护我们整个互联网通信安全的加密密钥体系。