好的,我们这次来学习一个非常重要且实用的算法: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", 长度)
步骤四:总结与核心优势
整个过程可以可视化为一棵树:
早期秘密 (种子)
|
HKDF-Extract (盐: 服务器随机数)
|
握手秘密 (树根)
/ \
HKDF-Expand ... ... HKDF-Expand
/ \
[握手密钥] HKDF-Extract (盐: 握手消息哈希)
|
主秘密 (新树根)
/ \
HKDF-Expand HKDF-Expand
/ \
[客户端应用密钥] [服务器应用密钥]
TLS 1.3 密钥派生的核心优势:
- 密钥分离:每个用途(握手加密、应用数据加密、客户端到服务器、服务器到客户端)都有独立的密钥,互不影响。
- 前向安全:通过引入握手消息的哈希值来生成主秘密,确保了即使长期密钥泄露,过去的通信会话也无法被解密。
- 灵活性:HKDF 算法可以方便地扩展出任意数量和长度的密钥。
通过这个循序渐进的过程,TLS 1.3 安全、可靠地从一个小小的共享秘密,构建出了保护我们整个互联网通信安全的加密密钥体系。