4.1. Salt (盐值)
4.1. Salt (盐值)
在基于口令的密码学中, 盐值传统上用于生成与给定口令对应的大量密钥集, 其中根据盐值随机选择一个。通过应用密钥派生函数 KDF 选择集合中的单个密钥, 如下所示:
DK = KDF (P, S)
其中 DK 是派生密钥, P 是口令, S 是盐值。这有两个好处:
-
对手很难预计算对应于口令字典的所有密钥, 甚至是最可能的密钥。例如, 如果盐值长度为 64 位, 每个口令将有多达 2^64 个密钥。因此, 对手被限制为在执行基于口令的操作并且盐值已知后才能搜索口令。
-
不太可能两次选择相同的密钥。同样, 如果盐值长度为 64 位, 根据生日悖论 (Birthday Paradox), 直到产生约 2^32 个密钥之前, 密钥之间的 "碰撞" 机会不会变得显著。碰撞不太可能这一事实解决了使用某些加密和认证技术时可能出现的关于同一密钥多次使用之间交互的一些担忧。
在基于口令的加密中, 加密消息的一方只需在从口令派生加密密钥时选择一个大的且足够随机的盐值, 就可以确保实现这些好处。生成消息认证码的一方可以以类似的方式获得这种保证。
然而, 解密消息或验证消息认证码的一方无法确定另一方提供的盐值实际上是随机生成的。例如, 盐值可能已从另一个基于口令的操作中复制, 试图利用同一密钥多次使用之间的交互。例如, 假设两个合法方交换加密消息, 其中加密密钥是从带有某个盐值的共享口令派生的 80 位密钥。对手可以从该加密中获取盐值并将其提供给其中一方, 就好像它是用于 40 位密钥一样。如果该方透露使用 40 位密钥解密的结果, 对手可能能够求解 40 位密钥。如果 40 位密钥是 80 位密钥的前半部分, 对手就可以轻松求解 80 位密钥的剩余 40 位。
为了防御此类攻击, 应仔细分析同一密钥多次使用之间的交互, 或者盐值应包含明确区分不同操作的数据。例如, 盐值可能有一个额外的非随机八位字节, 指定派生密钥是用于加密、消息认证还是其他操作。
基于此, 建议采用以下盐值选择方式:
-
如果不担心同一密钥 (或该密钥的前缀) 的多次使用与给定口令支持的基于口令的加密和认证技术之间的交互, 则盐值可以随机生成, 并且接收盐值的一方无需检查特定格式。它应该至少为八个八位字节 (64 位) 长。
-
否则, 盐值除了至少八个八位字节长的随机部分外, 还应包含明确区分不同操作和不同密钥长度的数据, 接收盐值的一方应检查或重新生成这些数据。例如, 盐值可以有一个额外的非随机八位字节, 指定派生密钥的用途。或者, 它可以是结构的编码, 该结构指定关于派生密钥的详细信息, 例如加密或认证技术以及从口令派生的不同密钥中的序列号。附加数据的特定格式留给应用程序决定。
注意: 如果随机数生成器或伪随机生成器不可用, 生成盐值 (或其随机部分) 的确定性替代方法是对口令和要处理的消息 M 应用基于口令的密钥派生函数。例如, 可以使用密钥派生函数计算盐值, 如 S = KDF (P, M)。但是, 如果已知消息 M 属于小消息空间 (例如 "Yes" 或 "No"), 则不建议采用此方法, 因为那样只会有少量可能的盐值。