10. 安全注意事项 (Security Considerations)
本节包含关于本文档所描述的哈希到曲线机制的额外安全注意事项。
10.1. 编码的性质 (Properties of Encodings)
每种编码类型(第 3 节)都接受任意字节串,并将其映射到曲线上的一点,该点取自依赖于编码类型的分布。需要注意,使用非均匀编码或直接对第 6 节的某一映射求值时,所产生的输出很容易与均匀随机点区分开来。使用非均匀编码的应用 SHOULD 仔细分析非均匀性带来的安全影响。当所需编码不明确时,应用 SHOULD 使用均匀编码。
第 3 节给出的两种编码都可能输出群 G 的单位元。对于任意随机输入,任一编码函数输出单位元的概率大约为 1/r,这对于密码学有用的椭圆曲线而言可以忽略不计。此外,要找到一个输入使其对应输出为单位元,在计算上是不可行的。(当编码函数以遵循第 5 节所有指南的 hash_to_field 函数实例化时,这两个性质都成立。)使用这些编码函数的协议 SHOULD NOT 添加特例来检测并"修正"单位元。
当 hash_to_curve 函数(第 3 节)以不可区分于随机预言机的 hash_to_field 函数实例化时(第 5 节),所得函数就不可区分于随机预言机([MRH04] [BCIMRT10] [FFSTV13] [LBB19] [H20])。在许多情况下,这样的函数可以安全地用于安全性分析假定一个输出椭圆曲线上均匀随机点的随机预言机的密码学协议。然而,正如 Ristenpart 等人在 [RSS11] 中所讨论的,并非所有依赖于随机预言机的安全性证明,在这些预言机被替换为不可区分功能后仍然成立。在分析依赖于 hash_to_curve 函数的协议的安全性时,应当考虑这一限制。
10.2. 哈希口令 (Hashing Passwords)
当使用本文档描述的任何函数哈希口令时,得知哈希函数输出(或潜在的任何中间值,例如 hash_to_field 的输出)的敌手可能实施字典攻击。为缓解此类攻击,建议先对口令执行一个开销更大的密钥派生函数(例如 PBKDF2 [RFC8018]、scrypt [RFC7914] 或 Argon2 [RFC9106]),然后将该函数的输出哈希到目标椭圆曲线。为保证抗碰撞性,底层密钥派生函数所用的哈希应按照第 5.3.1 节的指南来选择。
10.3. 常量时间要求 (Constant-Time Requirements)
本文档中所有函数的常量时间实现,对于所有用途都 STRONGLY RECOMMENDED,以避免通过侧信道泄露信息。当编码的输入为秘密值时,使用常量时间实现尤为重要;在这种情况下,针对时序攻击(例如 [VR20])的安全性 REQUIRES 常量时间实现。当要求常量时间实现时,所有基本操作和工具函数都必须以常量时间实现,如第 4 节所讨论。在某些应用中(例如嵌入式系统),通过其他侧信道(例如功耗或电磁侧信道)的泄露可能也很重要。防御此类泄露超出了本文档的范围,因为泄露的性质与适当的防御措施都依赖于具体应用。
10.4. encode_to_curve:输出分布与不可区分性 (encode_to_curve: Output Distribution and Indifferentiability)
encode_to_curve 函数(第 3 节)返回的点取自一个统计上远离均匀分布的分布。该分布大致以如下方式界定:首先,它至少包含 G 中八分之一的点;其次,该分布中点的概率变化最多为一个因子 4。当 encode_to_curve 以第 6 节任意 map_to_curve 函数实例化时,这些界限均成立。
上述界限源自文献中的若干工作。具体而言:
-
Shallue 和 van de Woestijne [SW06] 以及 Fouque 和 Tibouchi [FT12] 推导了关于 Shallue-van de Woestijne 映射(第 6.6.1 节)的界限。
-
Fouque 和 Tibouchi [FT10] 以及 Tibouchi [T14] 推导了关于 Simplified SWU 映射(第 6.6.2 节和第 6.6.3 节)的界限。
-
Bernstein 等人 [BHKL13] 推导了关于 Elligator 2 映射(第 6.7.1 节和第 6.8.2 节)的界限。
encode_to_curve 的不可区分性可由 Brier 等人 [BCIMRT10] 给出的论证类推而来;我们简要勾勒该论证如下。考虑一个理想的随机预言机 Hc(),它从 encode_to_curve 所调用的 map_to_curve 函数诱导出的分布中采样;为简便起见,假定目标椭圆曲线的余因子为 1(对于非 1 余因子有类似的论证)。不可区分性成立,当且仅当能够有效模拟 encode_to_curve 中的"内部"随机预言机,即 hash_to_field。模拟器工作方式如下:对于新的查询 msg,模拟器查询 Hc(msg) 并收到 map_to_curve 像集中的一点 P(如果 msg 与先前某个查询相同,模拟器就返回对该查询所给出的值)。模拟器随后计算 P 在 map_to_curve 下的可能原像,即满足 map_to_curve(u) == P 的 F 中元素 u(Tibouchi [T14] 表明,对于 Shallue-van de Woestijne 和 Simplified SWU 映射,这可以有效完成;Bernstein 等人也针对 Elligator 2 给出了相同的结论)。模拟器随机选取这样一个原像,并将其作为被模拟的"内部"随机预言机的输出返回。根据假设,Hc() 从 map_to_curve 在 F 的均匀随机输入元素上所诱导的分布中采样,因此该值是均匀随机的,并且在通过 map_to_curve 时诱导出正确的点 P。
10.5. hash_to_field 的安全性 (hash_to_field Security)
第 5 节定义的 hash_to_field 函数,当 expand_message(第 5.3 节)被建模为随机预言机时,不可区分于随机预言机 [MRH04]。由于不可区分性证明是可组合的,当 expand_message 相对于一个被建模为随机预言机的底层原语被证明不可区分于随机预言机时,此结论同样成立。当遵循第 5.3 节的指南时,该节定义的两个 expand_message 变体都满足此要求(另见第 10.6 节)。
我们非常简要地勾勒 hash_to_field 的不可区分性论证。注意,hash_to_field 返回的每一个模 p 的整数(即 F 的向量表示的每一个元素),都属于一个等价类,该类包含大约 2^k 个长度为 log2(p) + k 比特、且在模 p 下均相等的整数。对于 hash_to_field 返回的每一个模 p 的整数,模拟器从该等价类中随机采样一个成员,并输出由 I2OSP 返回的字节串。(注意这本质上就是 hash_to_field 过程的逆过程。)
10.6. expand_message_xmd 的安全性 (expand_message_xmd Security)
第 5.3.1 节定义的 expand_message_xmd 函数,当以下任一情况成立时,不可区分于随机预言机 [MRH04]:
-
H 不可区分于随机预言机,
-
H 是基于海绵结构的哈希函数,其内层函数被建模为随机变换或随机置换 [BDPV08],或者
-
H 是 Merkle-Damgard 哈希函数,其压缩函数被建模为随机预言机 [CDMP05]。
对于情形 (1) 和 (2),expand_message_xmd 的不可区分性直接源于 H 的不可区分性。
对于情形 (3),即 H 为 Merkle-Damgard 哈希函数时,不可区分性源于 [CDMP05] 的定理 5。具体而言,expand_message_xmd 通过在一个零块加上辅助信息(长度、计数器和 DST)的前缀下计算 b_0。然后,expand_message_xmd 中的每个输出块 b_i(i >= 1)都是对 b_0 的一个唯一的、无前缀编码调用 H 的结果。这成立,首先是因为所有这些调用输入的长度由 H 和 DST 的选择固定且相等;其次是因为每个这样的输入都有一个唯一的后缀(因为包含了计数器字节 I2OSP(i, 1))。
[CDMP05] 中讨论的构造与 expand_message_xmd 的本质区别在于,后者哈希了一个附加到 strxor(b_0, b_(i - 1)) 上的计数器({hashtofield-expand-xmd},第 10 步),而非附加到 b_0 上。这种方法增大了 H 不同调用之间的汉明距离,从而降低了 H 中的非理想性影响 b_i 值分布的可能性。
我们注意到,expand_message_xmd 可用于基于任何满足上述标准之一的哈希函数,实例化一个具有可变长度输出的通用不可区分功能。在 hash_to_field 之外使用 expand_message_xmd 的应用,应当通过为 DST 选取一个不同的值来确保域分离。
10.7. expand_message 变体的域分离 (Domain Separation for expand_message Variants)
如第 2.2.5 节所讨论,域分离的目的是确保:即使所有独立随机预言机都基于一个底层函数 H 实例化,那些查询多个独立随机预言机的密码学协议的安全性分析仍然有效。
本文档中的 expand_message 变体(第 5.3 节)通过对 H(底层哈希或可扩展输出函数)所哈希的所有字符串附加一个无后缀编码的域分离标签 DST_prime,来确保域分离。(遵循第 5.3.4 节指南的其他 expand_message 变体预期表现类似,但这些应当逐一分析。)为了安全性,在 expand_message 之外使用同一函数 H 的应用,应当强制这些 H 的用法与 expand_message 之间的域分离,并且应当将这一切与 H 在其他应用中的用法相互分离。
本节建议了四种强制与 expand_message 变体进行域分离的方法,解释了每种方法如何实现域分离,并列出了各自适用的情况。这些方法具有一个高层结构:应用设计者固定一个与 DST_prime 不同的标签 DST_ext,并用 DST_ext 来增强对 H 的调用。每种方法以不同方式增强对 H 的调用,并且每种方法可能对 DST_ext 施加额外要求。
这些方法可用于通过为每个方法选取不同的 DST_ext 值(例如 DST_ext1、DST_ext2)来实例化多个域分离的函数(例如 H1 和 H2)。
-
(仅后缀域分离。)当需要将 H 的调用与 expand_message_xmd 或 expand_message_xof 进行域分离时,此方法很有用。它不适用于将 expand_message 与 HMAC-H [RFC2104] 进行域分离;为此目的,见方法 4。
要实例化一个仅后缀域分离的函数 Hso,计算
Hso(msg) = H(msg || DST_ext)
DST_ext 应当采用无后缀编码(例如通过附加一个编码 DST_ext 长度的字节),以使找到哈希到相同值的不同 (msg, DST_ext) 对变得不可行。
此方法确保了域分离,因为所有对 H 的不同调用都有不同的后缀,由于 DST_ext 与 DST_prime 不同。
-
(前缀-后缀域分离。)此方法可用于与仅后缀方法相同的情况。
要实例化一个前缀-后缀域分离的函数 Hps,计算
Hps(msg) = H(DST_ext || msg || I2OSP(0, 1))
DST_ext 应当采用无前缀编码(例如通过添加一个编码 DST_ext 长度的单字节前缀),以使找到哈希到相同值的不同 (msg, DST_ext) 对变得不可行。
此方法确保了域分离,因为附加的字节 I2OSP(0, 1) 确保了 Hps 内部对 H 的输入与 expand_message 内部对 H 的输入是不同的。具体而言,DST_prime 的最后一个字节编码了 DST 的长度,该长度按要求为非零(第 3.1 节,要求 2),并且 DST_prime 总是被附加到 expand_message 内部对 H 的调用上。
-
(仅前缀域分离。)此方法仅对将 H 的调用与 expand_message_xmd 进行域分离有用。它不为 expand_message_xof 或 HMAC-H 提供域分离。
要实例化一个仅前缀域分离的函数 Hpo,计算
Hpo(msg) = H(DST_ext || msg)
为了使此方法提供域分离,DST_ext 的长度 SHOULD 至少为 b 比特,其中 b 是哈希函数 H 输出的比特数。此外,其前 b 比特中至少有一个必须为非零。最后,DST_ext SHOULD 采用无前缀编码(例如通过添加一个编码 DST_ext 长度的单字节前缀),以使找到哈希到相同值的不同 (msg, DST_ext) 对变得不可行。
此方法如下确保域分离。首先,由于 DST_ext 在其前 b 比特中至少包含一个非零比特,它保证与值 Z_pad(第 5.3.1 节,第 4 步)不同,这确保了所有对 H 的输入都与 expand_message_xmd 中用于生成 b_0 的输入不同。其次,由于 DST_ext 至少为 b 比特长,它几乎肯定与值 b_0 和 strxor(b_0, b_(i - 1)) 不同,因此所有对 H 的输入都极可能与用于生成 b_i(i >= 1)的输入不同。
-
(XMD-HMAC 域分离。)此方法对于将 HMAC-H 内部对 H 的调用(即使用哈希函数 H 实例化的 HMAC [RFC2104])与 expand_message_xmd 进行域分离很有用。如下文所讨论,它同样适用于 HKDF-H(即使用哈希函数 H 实例化的 HKDF [RFC5869])。
具体而言,当 HMAC-H 使用一个非秘密密钥来实例化基于哈希函数 H 的随机预言机时,此方法适用(注意 expand_message_xmd 也可用于此目的;见第 10.6 节)。当使用 HMAC-H 配合一个高熵秘密密钥时,域分离是不必要的;相关讨论见下文。
要选择一个确保与 expand_message_xmd 域分离的非秘密 HMAC 密钥 DST_key,计算
DST_key_preimage = "DERIVE-HMAC-KEY-" || DST_ext || I2OSP(0, 1) DST_key = H(DST_key_preimage)
然后,要使用 HMAC-H 实例化随机预言机 Hro,计算
Hro(msg) = HMAC-H(DST_key, msg)
DST_key_preimage 中末尾的零字节确保了该值与 expand_message_xmd 内部对 H 的输入不同(因为所有这些输入都有后缀 DST_prime,如前所述,其不能以零字节结尾)。这确保了域分离,因为以压倒性概率,使用密钥 DST_key 的 HMAC-H 内部对 H 的所有输入,其前缀都与 expand_message_xmd 内部的 Z_pad、b_0 和 strxor(b_0, b_(i - 1)) 值不同。
对于使用高熵秘密密钥来实例化私有随机预言机的 HMAC-H 用法,与 expand_message_xmd 的域分离是不必要的。这是因为,类似于上文情形,使用此秘密密钥的 HMAC-H 内部对 H 的所有输入,都几乎肯定与 expand_message_xmd 内部对 H 的所有输入具有不同的前缀。
最后,此方法可与 HKDF-H [RFC5869] 一起使用,方法是将 HKDF-Extract 的 salt 输入固定为按上述方式计算的 DST_key。这通过对 HMAC-H 使用 DST_key 的相同论证,确保了 HKDF-Extract 的域分离。此外,假设提供给 HKDF-Extract 的输入密钥材料(IKM)具有足够高的熵(例如与安全参数相称),HKDF-Expand 步骤通过类似于使用高熵秘密密钥的 HMAC-H 的相同论证(因为伪随机密钥正是如此)实现域分离。
10.8. 目标安全级别 (Target Security Levels)
每个密码套件都为其底层曲线指定了一个目标安全级别(以比特计)。该参数确保了相应的 hash_to_field 实例化是保守且正确的。我们强调,该参数仅仅是曲线安全级别的上界,既不是对其适用于某个给定应用的保证,也不是对其适用性的背书。数学与密码学的进步可能会降低任何曲线的有效安全级别。