HKDF的FIPS合规性深度解析

本文深入探讨基于HMAC的密钥派生函数HKDF在FIPS标准下的合规性,涵盖SP 800-56C、SP 800-108和SP 800-133等关键规范,分析其在不同应用场景下的技术实现要求与测试验证方法。

HKDF的FIPS合规性

HKDF是基于HMAC的密钥派生函数,规范定义于RFC 5869。它设计精良,我们通常喜欢使用它。FIPS(联邦信息处理标准)通常指由美国国家标准与技术研究院发布的一系列标准、建议和指南,更具体地指FIPS 140,这是关于密码模块验证的标准。许多监管环境(如FedRAMP)要求符合FIPS 140标准,而这往往限制了我们使用优秀工具的自由。今年早些时候,我决定迎难而上,为Go密码学标准库争取FIPS 140-3验证,同时尽量保留优秀特性,因此我深入研究了哪些做法被允许、哪些不被允许。

HKDF的FIPS合规性是一个有些混乱且存在争议的话题,部分原因是规范性引用分散在至少四份独立文档中,但实际上它几乎被批准用于任何目的。

标准框架

NIST SP 800-133 Rev. 2《密码密钥生成建议》在第6.2节讨论了对称密钥的派生,并提出了两类密钥派生方法:

  • 一步KDF,定义于SP 800-108(通用用途)或SP 800-56C(用于密钥协商方案产生的共享密钥)
  • 两步提取-扩展密钥派生过程,定义于第6.3节(提取)和SP 800-108(扩展)用于通用用途,或再次在SP 800-56C中作为密钥协商方案的一部分使用

这里的路径分叉,取决于HKDF是否作为密钥协商方案的一部分使用。

作为密钥协商组成部分的HKDF

从密钥协商案例开始讨论更为直接。NIST SP 800-56C Rev. 2《密钥建立方案中密钥派生方法建议》在第5节提出了两步密钥派生。如第5.1节底部所确认,当使用HMAC实例化、空IV和反馈模式KDF进行扩展时,这等同于HKDF。

RFC 5869规定了使用HMAC进行提取和扩展步骤的上述提取-扩展密钥派生过程版本。

盐可以协商、为固定值或全零,就像在HKDF中一样。只要在两者中使用相同的HMAC函数,明确允许将一个提取步骤的输出用于多个扩展操作。

输入密钥材料可以与其他值连接,这是Diffie-Hellman贡献的常见做法:

本建议允许使用形式为Z’ = Z || T的"混合"共享密钥,该连接由在执行密钥建立方案期间生成的"标准"共享密钥Z(如[SP 800-56A]或[SP 800-56B]中当前规定)和已使用其他方法生成的辅助共享密钥T组成。

作为密钥协商一部分的HKDF可以根据IG D.F作为"KDA HKDF Sp800-56Cr2"进行独立的CAVP测试。

HKDF-Extract作为KDA OneStepNoCounter

SP 800-56C中定义的一步密钥派生是基于计数器的KDF,因此不允许单独使用HKDF-Extract而不使用HKDF-Expand。然而,实施指南D.P"SP 800-56Crev2无计数器一步密钥派生函数"引入了如果输出大小小于或等于哈希输出大小则无需计数器的变体。

当使用HMAC时,它归结为HMAC(salt, Z || FixedInfo),也就是HKDF-Extract。这可以作为"KDA OneStepNoCounter Sp800-56Cr2"进行CAVP测试。

作为通用KDF的HKDF

直到最近,我还认为HKDF仅被允许作为密钥协商的一部分。但事实并非如此!

HKDF-Expand作为SP 800-108 KDF

HKDF-Expand本身实际上是NIST SP 800-108 Rev. 1 Upd. 1《使用伪随机函数进行密钥派生的建议》中定义的一种模式,该标准定义了经批准的通用KDF(并被上述SP 800-133引用用于一步KDF)。

我最初认为情况并非如此,因为反馈模式KDF在第4.2节中定义为计算HMAC(K_in, K(i-1) || i || FixedInfo),而HKDF-Expand计算HMAC(K_in, K(i-1) || info || i)。注意计数器i和信息的顺序。SP 800-108反馈模式KDF中的其他所有内容都可以调整以达到HKDF,但我在文本中没有找到允许交换顺序的内容。

然而,SP 800-56C明确声称HKDF是其两步密钥派生方法的一个配置文件,并仅通过引用SP 800-108来描述扩展步骤!

应使用SP 800-108中定义的基于PRF的通用密钥派生函数之一进行密钥扩展。

为了确认这一点,我查看了SP 800-108的ACVP测试,确实有一个fixedDataOrder参数,“描述计数器出现在固定数据中的位置”,可以设置为"after fixed data"。相关的ACVP测试向量在应用于HKDF-Expand时通过,证明它是SP 800-108的批准版本。

请注意,为了以批准的操作模式为此目的使用HKDF-Expand,FIPS 140密码模块需要在其证书中包含SP 800-108反馈KDF。

根据SP 800-133的HKDF-Extract

好的,所以HKDF-Expand是通用KDF,但HKDF-Extract呢?

2020年发布的SP 800-133 Rev. 2在第6.3节"通过组合(多个)密钥和其他数据生成的对称密钥"中添加了一种新方法。新的方法3,称为"密钥提取过程",就是HMAC(salt, K || … || D || …),也就是HKDF-Extract!

虽然其他方法需要多个密钥,或同时需要密钥和其他数据,但方法3要求n(密钥数量)≥ 1且m(其他数据)≥ 0,因此明确允许即使只有单个密钥作为输入。盐可以是秘密或非秘密值。明确允许密钥和数据的替代排序。

IG 2.4.B确认了这一点,其中指出"[基于HKDF的] TLS 1.3 KDF内执行的基础功能映射到NIST批准的标准,即:SP 800-133rev2(第6.3节选项#3)、SP 800-56Crev2和SP 800-108"。

SP 800-133第6.3节没有CAVP测试或CAST要求,但IG D.H要求模块证书中的供应商确认。

需要对本标准第4节和第6.3节涵盖的所有方法进行供应商对SP 800-133的确认;[…]安全策略应提供每种方法的详细信息。[…]如果为SP 800-133声称供应商确认,除了根据IG 10.3.A对基础批准算法所需的CAST之外,没有特定的CAST要求。

附加评论4甚至特意批准了第6.2(3)节。

通过SP 800-133rev2第6.3节第3项定义的密钥提取过程生成密钥的方法对SP 800-133系列是新的。本实施指南发布后,该方法在批准模式下被批准使用。

不过有一个问题。同一IG说至少一个输入密钥必须从DRBG生成,因此在我看来,不能将KDF的输出作为密钥输入到HKDF-Extract中(与根据第6节和IG D.M的SP 800-108 KDF不同)。

(a) 至少一个组件密钥K1, …, Kn按照SP 800-133第4节所示生成,且满足第6.3节的独立性要求,且(b) 组件密钥K1, …, Kn中没有一个是从密码生成的。

总结

如果你正在进行密钥协商,可以根据SP 800-56C Rev. 2使用HKDF,或根据IG D.P使用HKDF-Extract。如果不是,你可以根据SP 800-133 Rev. 2(第6.3节选项#3)使用HKDF-Extract将随机生成的密钥与其他密钥和/或数据组合,并根据SP 800-108使用HKDF-Expand作为通用KDF。

我应该指出这是合理的,因为如果你有高质量密钥(与共享密钥相反,这种情况下适用SP 800-56C),通常可以跳过提取步骤,直接进入SP 800-108用途。如果你想组合多个密钥,或密钥和其他数据,你会想要进行提取,而这正是SP 800-133第6.3节所涵盖的。

请记住,使用批准的算法只是成功的一半,因为FIPS 140合规性还要求使用经过这些算法验证的模块。计划的Go FIPS模块将测试HKDF作为SP 800-56Crev2、IG D.P和SP 800-133,并将供应商确认SP 800-133rev2支持,使其在可能的所有地方都可使用。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计