TLS 1.2 中的 PRF(伪随机函数)与密钥派生过程详解
字数 3229 2025-12-16 05:12:56

TLS 1.2 中的 PRF(伪随机函数)与密钥派生过程详解

题目描述
在 TLS 1.2 协议中,PRF(Pseudo-Random Function,伪随机函数)是一个核心组件,用于从主密钥(Master Secret)派生出会话所需的各类密钥材料(如客户端和服务器端的加密密钥、MAC 密钥、初始化向量等)。本题将详细讲解 TLS 1.2 中 PRF 的设计结构、工作流程,以及如何通过该 PRF 生成密钥块(key block),并最终分割出各个密钥。我们将专注于 TLS 1.2 中使用的基于 HMAC 的 PRF 结构。

解题过程

第一步:理解 PRF 在 TLS 1.2 中的作用与输入
TLS 1.2 的密钥派生分为两个主要阶段:

  1. 预主密钥 → 主密钥:使用 PRF 从预主密钥(Pre-Master Secret)、客户端和服务器随机数(ClientHello.random 和 ServerHello.random)计算得到 48 字节的主密钥(Master Secret)。
  2. 主密钥 → 密钥材料:再次使用 PRF,从主密钥、客户端和服务器随机数计算出一个足够长的密钥块(key block),然后按顺序分割出客户端写 MAC 密钥、服务器写 MAC 密钥、客户端写加密密钥、服务器写加密密钥等。

PRF 在两次计算中结构相同,只是输入参数不同。PRF 定义为:
PRF(secret, label, seed) = P_<hash>(secret, label + seed)
其中:

  • secret:密钥材料,第一阶段是预主密钥,第二阶段是主密钥。
  • label:一个 ASCII 字符串标签,用于区分不同的派生用途(例如,"master secret" 或 "key expansion")。
  • seed:种子,由客户端随机数和服务器随机数拼接而成。
  • P_<hash>:一个扩展函数,使用两种哈希算法(在 TLS 1.2 中默认为 SHA-256 和 MD5)进行组合,但在大多数现代实现中,当使用 TLS 1.2 且密码套件指定了单一哈希算法(如 SHA-256)时,PRF 可简化为仅使用该种哈希算法的 HMAC。

为了通用性,我们讲解 TLS 1.2 RFC 中定义的、同时使用 MD5 和 SHA-1(或 SHA-256)的“传统”PRF 结构,这也是理解其设计的关键。

第二步:剖析 PRF 的核心扩展函数 P_hash
P_hash(secret, seed) 是一个基于 HMAC 的扩展函数,用于生成任意长度的伪随机字节流。

  1. 定义P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + HMAC_hash(secret, A(2) + seed) + HMAC_hash(secret, A(3) + seed) + ...
    其中 + 表示字节拼接。
  2. A(i) 的计算
    • A(0) = seed
    • A(1) = HMAC_hash(secret, A(0))
    • A(2) = HMAC_hash(secret, A(1))
    • A(3) = HMAC_hash(secret, A(2))
    • ...
    • 通用公式:A(i) = HMAC_hash(secret, A(i-1)),其中 i >= 1
  3. 工作原理
    • 首先计算 A(1) = HMAC_hash(secret, seed)
    • 输出第一块数据:HMAC_hash(secret, A(1) + seed)
    • 计算 A(2) = HMAC_hash(secret, A(1))
    • 输出第二块数据:HMAC_hash(secret, A(2) + seed)
    • 重复此过程,直到生成的字节总数达到所需长度。
    • 每次迭代都使用同一个 secretseed,但 A(i) 不断更新,确保输出的每一块都不同。

第三步:构建完整的 PRF——组合两种哈希算法
TLS 1.2 的 PRF 将两个 P_hash 实例(一个使用 MD5,一个使用 SHA-1 或 SHA-256)的输出进行异或(XOR)组合。

  1. 公式PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR P_SHA256(S2, label + seed)
  2. 密钥分割secret 被分割成两半 S1S2
    • 如果 secret 长度是偶数,则 S1 取前半部分,S2 取后半部分。
    • 如果 secret 长度是奇数,则 S1 取前半部分(包括中间字节),S2 取后半部分(包括中间字节)。具体来说,S1 = secret[0 .. (length+1)/2]S2 = secret[(length-1)/2 .. length-1]
  3. 设计意图:这种组合利用了 MD5 的速度优势和 SHA 系列的安全性,旨在通过组合不同密码学原语来增强安全性(“组合密码学”思路)。但在 TLS 1.2 中,对于使用 SHA-256 的密码套件,PRF 可以直接用 P_SHA256 单独实现,无需 MD5 参与。

第四步:密钥派生全过程示例(从主密钥到密钥块)
假设我们正在派生密钥材料,使用的密码套件需要以下密钥(长度取决于密码套件):

  • 客户端写 MAC 密钥
  • 服务器写 MAC 密钥
  • 客户端写加密密钥
  • 服务器写加密密钥
  • 客户端写 IV(如果需要)
  • 服务器写 IV(如果需要)
  1. 确定密钥块总长度:根据协商的密码套件,确定每个密钥和 IV 所需的字节数,将它们相加得到密钥块的总长度 key_block_length
  2. 计算密钥块
    key_block = PRF(master_secret, "key expansion", server_random + client_random),直到输出 key_block_length 字节。
    注意:这里 seed 是 server_random + client_random,顺序固定。
  3. 分割密钥块:按照密码套件定义的固定顺序,将 key_block 分割成独立的密钥和 IV。
    例如:key_block = client_write_MAC_key || server_write_MAC_key || client_write_encryption_key || server_write_encryption_key || client_write_IV || server_write_IV
    每个部分按预定义长度依次切分。

第五步:总结与安全性要点

  • 伪随机性:PRF 的设计目标是在 secret 保密且 seed 公开的情况下,其输出在计算上不可区分于真正的随机串。
  • 前向安全性:由于每次会话的 client_randomserver_random 不同,即使主密钥泄露,攻击者也无法推算出之前或之后会话的密钥材料。
  • 密钥分离:通过使用不同的 label("master secret" 和 "key expansion")和不同的 seed(随机数顺序可能不同),确保了不同阶段的密钥材料是独立的。
  • 演进:在 TLS 1.3 中,PRF 被更简洁、更安全的 HKDF 所取代,但理解 TLS 1.2 的 PRF 对于掌握协议演进和遗留系统分析至关重要。

通过以上步骤,我们循序渐进地解析了 TLS 1.2 中 PRF 的结构、其核心组件 P_hash 的工作机制、以及如何利用 PRF 完成从主密钥到具体会话密钥的安全派生过程。

TLS 1.2 中的 PRF(伪随机函数)与密钥派生过程详解 题目描述 在 TLS 1.2 协议中,PRF(Pseudo-Random Function,伪随机函数)是一个核心组件,用于从主密钥(Master Secret)派生出会话所需的各类密钥材料(如客户端和服务器端的加密密钥、MAC 密钥、初始化向量等)。本题将详细讲解 TLS 1.2 中 PRF 的设计结构、工作流程,以及如何通过该 PRF 生成密钥块(key block),并最终分割出各个密钥。我们将专注于 TLS 1.2 中使用的基于 HMAC 的 PRF 结构。 解题过程 第一步:理解 PRF 在 TLS 1.2 中的作用与输入 TLS 1.2 的密钥派生分为两个主要阶段: 预主密钥 → 主密钥 :使用 PRF 从预主密钥(Pre-Master Secret)、客户端和服务器随机数(ClientHello.random 和 ServerHello.random)计算得到 48 字节的主密钥(Master Secret)。 主密钥 → 密钥材料 :再次使用 PRF,从主密钥、客户端和服务器随机数计算出一个足够长的密钥块(key block),然后按顺序分割出客户端写 MAC 密钥、服务器写 MAC 密钥、客户端写加密密钥、服务器写加密密钥等。 PRF 在两次计算中结构相同,只是输入参数不同。PRF 定义为: PRF(secret, label, seed) = P_<hash>(secret, label + seed) 其中: secret :密钥材料,第一阶段是预主密钥,第二阶段是主密钥。 label :一个 ASCII 字符串标签,用于区分不同的派生用途(例如,"master secret" 或 "key expansion")。 seed :种子,由客户端随机数和服务器随机数拼接而成。 P_<hash> :一个扩展函数,使用两种哈希算法(在 TLS 1.2 中默认为 SHA-256 和 MD5)进行组合,但在大多数现代实现中,当使用 TLS 1.2 且密码套件指定了单一哈希算法(如 SHA-256)时,PRF 可简化为仅使用该种哈希算法的 HMAC。 为了通用性,我们讲解 TLS 1.2 RFC 中定义的、同时使用 MD5 和 SHA-1(或 SHA-256)的“传统”PRF 结构,这也是理解其设计的关键。 第二步:剖析 PRF 的核心扩展函数 P_ hash P_hash(secret, seed) 是一个基于 HMAC 的扩展函数,用于生成任意长度的伪随机字节流。 定义 : P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + HMAC_hash(secret, A(2) + seed) + HMAC_hash(secret, A(3) + seed) + ... 其中 + 表示字节拼接。 A(i) 的计算 : A(0) = seed A(1) = HMAC_hash(secret, A(0)) A(2) = HMAC_hash(secret, A(1)) A(3) = HMAC_hash(secret, A(2)) ... 通用公式: A(i) = HMAC_hash(secret, A(i-1)) ,其中 i >= 1 。 工作原理 : 首先计算 A(1) = HMAC_hash(secret, seed) 。 输出第一块数据: HMAC_hash(secret, A(1) + seed) 。 计算 A(2) = HMAC_hash(secret, A(1)) 。 输出第二块数据: HMAC_hash(secret, A(2) + seed) 。 重复此过程,直到生成的字节总数达到所需长度。 每次迭代都使用同一个 secret 和 seed ,但 A(i) 不断更新,确保输出的每一块都不同。 第三步:构建完整的 PRF——组合两种哈希算法 TLS 1.2 的 PRF 将两个 P_hash 实例(一个使用 MD5,一个使用 SHA-1 或 SHA-256)的输出进行异或(XOR)组合。 公式 : PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR P_SHA256(S2, label + seed) 。 密钥分割 : secret 被分割成两半 S1 和 S2 。 如果 secret 长度是偶数,则 S1 取前半部分, S2 取后半部分。 如果 secret 长度是奇数,则 S1 取前半部分(包括中间字节), S2 取后半部分(包括中间字节)。具体来说, S1 = secret[0 .. (length+1)/2] , S2 = secret[(length-1)/2 .. length-1] 。 设计意图 :这种组合利用了 MD5 的速度优势和 SHA 系列的安全性,旨在通过组合不同密码学原语来增强安全性(“组合密码学”思路)。但在 TLS 1.2 中,对于使用 SHA-256 的密码套件,PRF 可以直接用 P_SHA256 单独实现,无需 MD5 参与。 第四步:密钥派生全过程示例(从主密钥到密钥块) 假设我们正在派生密钥材料,使用的密码套件需要以下密钥(长度取决于密码套件): 客户端写 MAC 密钥 服务器写 MAC 密钥 客户端写加密密钥 服务器写加密密钥 客户端写 IV(如果需要) 服务器写 IV(如果需要) 确定密钥块总长度 :根据协商的密码套件,确定每个密钥和 IV 所需的字节数,将它们相加得到密钥块的总长度 key_block_length 。 计算密钥块 : key_block = PRF(master_secret, "key expansion", server_random + client_random) ,直到输出 key_block_length 字节。 注意:这里 seed 是 server_random + client_random ,顺序固定。 分割密钥块 :按照密码套件定义的固定顺序,将 key_block 分割成独立的密钥和 IV。 例如: key_block = client_write_MAC_key || server_write_MAC_key || client_write_encryption_key || server_write_encryption_key || client_write_IV || server_write_IV 。 每个部分按预定义长度依次切分。 第五步:总结与安全性要点 伪随机性 :PRF 的设计目标是在 secret 保密且 seed 公开的情况下,其输出在计算上不可区分于真正的随机串。 前向安全性 :由于每次会话的 client_random 和 server_random 不同,即使主密钥泄露,攻击者也无法推算出之前或之后会话的密钥材料。 密钥分离 :通过使用不同的 label ("master secret" 和 "key expansion")和不同的 seed (随机数顺序可能不同),确保了不同阶段的密钥材料是独立的。 演进 :在 TLS 1.3 中,PRF 被更简洁、更安全的 HKDF 所取代,但理解 TLS 1.2 的 PRF 对于掌握协议演进和遗留系统分析至关重要。 通过以上步骤,我们循序渐进地解析了 TLS 1.2 中 PRF 的结构、其核心组件 P_hash 的工作机制、以及如何利用 PRF 完成从主密钥到具体会话密钥的安全派生过程。