密钥派生最佳实践

admin 2025年2月7日02:46:03评论3 views字数 5305阅读17分41秒阅读模式

密钥派生在许多加密应用中至关重要,包括密钥交换、密钥管理、安全通信和构建健壮的加密基元。但也很容易出错:尽管存在针对不同密钥派生需求的标准工具,但我们的审计经常会发现这些工具的不当使用可能会危及密钥安全。Flickr的API签名伪造漏洞是在密钥派生过程中滥用哈希函数的一个典型案例。

这些误用表明对密钥派生函数 (KDFs) 可能存在误解。本文介绍了使用 KDFs 的最佳实践,包括需要仔细处理密钥派生以实现所需安全属性的特殊场景。在此过程中,我们会针对下列常见问题给出建议,例如:

  • 我需要为 HKDF 添加额外的随机数吗?

  • 我应该在 HKDF 中使用盐吗?

  • 我是否应该使用不同的盐从 HKDF 派生多个密钥?

  • 如何组合多个来源的密钥内容?

在深入研究密钥派生最佳实践之前,我们来回顾一些重要的概念,以帮助我们更好地理解它们。

密钥内容的来源

密钥加密基元(如 AEADs)需要满足某些要求的密钥内容来保障安全性。在大多数情况下,基元要求密钥是随机均匀生成的,或者以接近标准随机的加密方式生成。我们将区分四种类型的密钥内容:

  • (标准) 随机,例如使用 OS CSPRNG 生成的 32 字节

  • 不均匀但熵高,比如密钥交换的输出

  • 低熵,例如密码和其他容易猜解到的值

  • 多个源的集合,例如前量子和后量子共享密钥

密钥派生最佳实践
上述最后一类与当前抗量子密码学的发展特别相关。混合密钥交换协议结合了经典密钥交换和后量子密钥交换,旨在预防先窃取,后解密(Harvest now, decrypt later)攻击。

密钥派生的工作原理

密钥派生是从某些初始密钥内容 (IKM) 生成可接受的密钥内容以供加密使用的过程。从加密学的角度来看,“可接受”通常意味着从所有可能的密钥集中随机统一选择,或者与真正的随机密钥无法区分。有两个主要的密钥派生工作与初始密钥内容的性质相关。

  • 随机性提取从具有“足够随机性”的 IKM 中提取加密密钥。随机性提取可以选择使用盐。自然地,我们可以将随机性提取应用于已经适合加密的密钥。

  • 随机性扩展从加密密钥派生子密钥。扩展通常使用每个子键唯一的 “context” 或 “info” 输入。

这种分类深受广泛使用的 KDF 算法 HKDF 的影响;其他 KDF 设计不一定遵循相同的原则。然而,提取和扩展在大多数 KDF 应用中得到了很好的反映。此外,我们还将考虑一个与复杂的密钥内容相关的其他 KDF 任务,例如一组源。

提取和扩展:HKDF 简介

HKDF 旨在提供提取和扩展。HKDF 通常由具有 API 的应用程序访问 。但是,在后台,会发生以下情况:首先,提取过程从 IKM 和 salt 生成伪随机密钥 (PRK)。然后,生成长度为 key_ len 的子密钥:。这里是一个wrapper,它通过重复调用 HMAC 来生成所需的输出;换句话说,它实现了一个可变长度的伪随机函数。对于给定的键,将为每个新输入返回所需长度的随机位串;固定值将始终产生相同的输出。如果保持不变但长度可变,则较小的输出将是较长输出的前缀。HKDF(ikm, salt, info, key_len)prk = HKDF.Extract(ikm, salt) = HMAC(salt, ikm)sub_key = feedback[HMAC](prk,info)feedback[HMAC]HMACfeedbackinfoinfoinfo

关于提取盐:HKDF 的提取阶段可以选择使用盐。提取盐是一个随机的非秘密值,用于从密钥内容中提取足够的随机性。至关重要的是,盐不能被攻击者控制,因为这通常会给 KDF 带来灾难性的后果。Hugo Krawczyk 提供了一个理论示例,说明攻击者控制的盐打破了盐和 IKM 之间的独立性,导致提取器存在脆弱性。然而,正如我们在下一节中讨论的那样,其后果也可能具有实际意义。许多应用程序(例如,经过身份验证的密钥交换除外)的一个典型痛点是验证盐。因此,HKDF标准建议大多数应用程序使用常量,例如全零字节字符串。不使用盐所付出的代价是对 HMAC 的更有力的假设,尽管仍然是合理的。

解决 KDF 误用问题

开发人员在选择 KDF 时必须考虑几个问题,但对 KDF 的误解可能会导致选择引入安全问题。下面,我们提供了滥用示例以及最佳实践,以帮助避免不当使用 KDF。

我应该使用不同的盐来派生多个子键吗?

使用上述 KDF 提取,子键生成更适合随机性扩展。给定一个伪随机键(可能在提取步骤后获得),可以使用每个子键的唯一信息输入通过随机性扩展来获取子键。盐用于提取。此外,如上所述,攻击者控制的盐可能对安全性有害。考虑一个按需生成用户密钥的密钥管理应用程序。一个实现可能决定使用用户名作为 salt 从主密钥派生密钥。除了自由选择他们的用户名外,用户还可以提供一个上下文字符串,以指示密钥的用途并确保不同的应用程序使用独立的密钥。核心功能如下面的代码片段所示:“file-encryption-key”

# For each subkeydef generate_user_key(username, purpose, key_len):    ikm = fetch_master_key_from_kms()    sub_key = hkdf(ikm=ikm, salt=username, info=purpose, key_len=key_len) 

图 3:使用主密钥按需派生密钥的密钥管理应用程序

这种结构很糟糕:由于 salt 被用作提取的 HMAC“密钥”,因此它首先由 PAD 或 HASH 方案(密钥填充密钥哈希)进行预处理以处理可变长度的密钥。在此实现中,如果您的用户名是 ,而我选择我的用户名为 ,那么我将获取您的所有密钥:b”A”*65``sha256(b”A”*65)

那么我们应该怎么做呢?首先要避免的是攻击者可能控制的盐。在上面的示例中,应用程序可以在初始化时生成随机盐,并根据需要从受信任的位置检索它。或者,应用程序也可以使用常量盐,如全零字节字符串,如 RFC 5869 建议。值得注意的是,对于 HMAC,如果已经是一个统一的随机密钥,则使用常量不需要更强的假设。最后,如果 IKM 最初是一个随机键,并且用户名被限制为我们讨论双 PRF .iks中描述的一组值,也可以避免该问题。

我应该使用什么作为 info 值?

应用程序必须确保每个新子密钥使用唯一值。在值中包含尽可能多的上下文信息也是一种很好的做法,例如会话标识符或脚本哈希。上下文的编码必须是单射的,例如,通过注意规范化问题infoinfoinfo

info 参数 HKDF 是否需要额外的随机性?

我们经常会遇到在参数中包含额外随机性以生成子密钥的实现。希望使 HKDF 更加随机。info

# For each subkeyextra_randomness = random(32)sub_key = hkdf(ikm=ikm, salt=salt, info=concat(info, extra_randomness), key_len=key_len) 

虽然这并没有什么坏处,但对随机性提取的初始任务也没有多大帮助。请注意,额外的随机性仅影响随机性扩展。考虑以下推演:如果 IKM 没有足够的熵,或者 HMAC 被证明是一个非常糟糕的随机性提取器,那么额外的随机性将无助于创建合适的密钥以在随机性扩展期间使用。用于随机性扩展的远非随机密钥偏离了安全要求,因此不提供任何安全保证。从上面的讨论来看,假设 HKDF 是安全的,如果有足够的随机数,我们会为它提取一个随机的 key。然后,扩展将确保 sub_key 与相同长度的随机 key 无法区分。此外,HKDF并不要求信息材料保密;它只需要对于每个子键是唯一的。ikm

但是,应用程序可能会使用额外的随机性来进一步保证信息输入的唯一性。除非你用这种额外的随机性做一些有趣的事情,否则你使用它不会变得更糟。

我应该在低熵输入上使用 HKDF 吗?

不。HKDF 仅包含几个 HMAC 调用。密码破解程序可以相当有效地破解大量 KDF 密码,这些密码并不是故意设计为缓慢且占用内存的。最好使用慢速、内存困难的算法(如 Argon2)进行哈希处理和从密码中派生密钥。此外,最好避免使用密码哈希作为加密数据的密钥。首选创建密钥层次结构(例如密钥加密密钥),使用密码哈希加密随机生成的密钥,以便根据需要从中派生更多密钥。

我应该将哈希函数用作通用 KDF 吗?

哈希函数不应用于 KDF 中的一般用途。在密钥派生过程中使用的信息由攻击者控制的情况下,使用哈希函数作为 KDF 可能会使应用程序面临长度扩展攻击。这些攻击是那些从密钥结合用户提供的数据生成随机性的应用程序的主要问题(如 Flickr 的 API 签名伪造漏洞)。相反,请首选 HKDF 和其他专为密钥派生而设计的 KDF。尽管哈希在特定情况下可以作为 KDF 接受,但我们警告不要这种做法,除非用户可以合理地正式争论其应用程序的使用。如果您的应用程序确实遭受一两个额外的压缩函数调用,并且您没有充分的理由使用现有 KDF,请咨询专家。此建议也适用于其他临时结构,例如 YOLO 结构

我应该对 AEAD 使用共享的 Diffie-Hellman 密钥吗?

AEAD(以及大多数其他键控对称算法)的安全协定需要适当长度的统一随机位串,以提供有意义的安全保证。DH 输出是高熵,但通常不是统一的位串。因此,将它们用作密钥偏离了安全协定。某些实现可能允许毫无戒心的用户对给定的原语使用错误的密钥材料(例如,将 DH 输出馈送到 Chacha20 密码中)。这种使用违反了 AEAD 结构的要求。

组合密钥

密码学中的一个常见任务是将一个原始的两个实例组合在一起,以便整体结构最强。自然,这是一个与密钥派生高度相关的问题:我们能否从一组密钥内容中推导出一个密钥,以便只要其中一个密钥内容是安全的,整个密钥就是安全的?混合密钥交换协议目前是该技术的相关用例。这些协议结合了通过经典和后量子密钥交换元素建立的密钥,以防止攻击者今天正在收集加密通信,并希望在有能力的量子计算机可用时解密它们。此类协议包括 PQXDHApple 的 PQ3 和后量子噪声。但是,密钥组合广泛用于与量子威胁无关的其他上下文,例如具有预共享密钥的 TLS1.3、双棘轮算法和 MLS。

那么,我们如何组合密钥呢?为简单起见,我们将以下讨论限制为两个密钥,即 .这项工作的经典工具是双 PRF。与 PRF 一样,双 PRF 采用密钥和输入,只要其中一个密钥或输入包含统一密钥,其行为就类似于 PRF。在双 PRF 中,您可以切换键值和输入值,而不会影响安全性。在实践中,双 PRF 最常见的实例是 HMAC。k_1``k_2

但是,将 HMAC 用作双 PRF 需要谨慎。标准化的 HMAC 允许可变长度的密钥,这些密钥通过 PAD 或 HASH 函数进行处理。PAD-or-HASH 不具有抗冲突性,为不受限制的 HMAC 密钥创建 HMAC 输出冲突是微不足道的。幸运的是,本文建立了 HMAC 的双 PRF 安全性,并充分表征了预期双 PRF 安全性的设置键。简而言之,HMAC 的安全双 PRF 使用要求 key 参数(即作为 key 传递给 HMAC 的内容)是固定长度的位串(即所有键必须具有相同的长度)或可变长度的位串,只要所有密钥的长度至少是底层哈希函数的块长度。

dual PRF 结果仅在组合两个标准随机字节串 时适用。尽管一些工作主张将 HMAC 用作双 PRF 和其他高熵输入,如 Diffie-Hellman 共享密钥 (),但更保守的用法会将初始提取步骤应用于每个需要它的密钥内容。这方面的一个例子是 。虽然一些分析取消了初始提取步骤,但这些用途偏离了 HMAC 现有的安全分析,并不直接享受安全保障。G^xy``prk = HMAC( HKDF.Extract(G^xy, salt), random_kem_secret)

使用双重 PRF 的另一个良好做法是确保最终的组合密钥尽可能多地依赖于上下文。这里的上下文可以是 Diffie-Hellman 的分享,(哈希的)完整的通信记录。一个好的解决方案是使用额外的扩展步骤,该步骤在扩展期间使用上下文作为输入。info

最后,还存在其他组合方法,例如串联 KDF (CatKDF)。CatKDF 在密钥的串联上大致使用 KDF。在其中一个密钥可能由攻击者控制的情况下,CatKDF 的安全性超出了现有的安全分析范围。上述评论并不意味着实际攻击,而是提高了人们对有时需要超出已知范围的更强大假设的情况的认识。有关实践中双 PRF 使用的进一步讨论,请参阅从单向和到 TLS 的实用(后量子)密钥组合器。

选择正确的工具

本文研究了不同的 KDF 工作、执行这些任务的适当工具,以及我们在实践中看到的一些典型误用。总而言之,我们邀请您在处理下一个 KDF 工作时做同样的事情。邀请如下:当您面临下一个 KDF 工作时,请退后一步,考虑更高级别的目标以及更高级别的工具是否更适合。

例如,您是否需要一个 KDF,因为您已经建立了一些 Diffie-Hellman 共享密钥并且必须创建一个“安全通道”?考虑使用现有的经过实战验证的密钥交换协议,如 NoiseTLS 1.3 或 EDHOC

您是否需要一个 KDF 来加密数据流的各个块,同时期望对块和整个流有一些安全保证?考虑改用流式AEAD!

原文始发于微信公众号(0x6270安全团队):密钥派生最佳实践

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年2月7日02:46:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   密钥派生最佳实践http://cn-sec.com/archives/3706957.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息