我正在尝试创建PBKDF2的实现来生成密钥以使用 AES-256 加密文件,但我有一个关于盐大小的问题。我计划使用 SHA-256 并与密码连接,如果连接的位串的大小大于 256 位,是否会有所不同,或者如果盐和密码都是 256 位,是否会被认为更安全,使他们的串联 512 位?
1 回答
首先,让我们备份并快速回顾一下PBKDF2:
PBKDF2 生成所需字节数的输出。它通过计算一些“块”来生成这些字节。每个块是所选散列的大小。例如,如果您希望导出一个 64 字节长的密钥,并且您希望使用产生 32 字节哈希的 SHA-256,您将生成 2 个 PBKDF2 块。最终输出是这些块的串联。
那么如何生成每个块呢?
好吧,(我将在这里使用 RFC 命名法),块是由函数生成的,F
. 这个函数接受用户密码P
、你的盐S
、期望的迭代计数c
和你正在生成的块的索引i
(基于一个)。
对于您的第一个块,您的函数调用将类似于:(F ("MySecretPassword", "random_salt", 100000, 1)
注意我使用的是 100k 次迭代。有关选择此值的更多信息,请参阅这篇文章。)
回顾 RFC:
F(P, S, c, i) = U_1 \xor U_2 \xor U_3 ... U_c
U_1 = PRF(P, S || INT(i))
U_2 = PRF(P, U_1)
U_3 = PRF(P, U_2)
...
U_c = PRF(P, U_{c-1})
PRF
代表伪随机函数。其中,对于 SHA-256,应该是基于 SHA-256 的 HMAC。该函数通过首先生成密码的 SHA-256 HMAC 来工作,使用与块号连接P
的盐。然后,该函数迭代(次),并将结果与先前的结果进行异或。每次迭代都使用 SHA-256 HMAC(再次)对密码进行哈希处理,但使用先前的结果作为 HMAC 密钥。S
i
c
P
所以 - 回到你的问题 - 因为我们使用的是 HMAC,所以盐长度无关紧要**并且可以超过 256 位。当 HMAC 提供的密钥(在这种情况下是您的密码)长于哈希输出的长度时,它将对密钥进行哈希处理以获得 256 位。如果提供的密钥短于 256 位,则会对其进行填充以获得正好 256 位。从某种意义上说,这些细节对您的实现是隐藏的,因此您不必担心将盐传递到 PBKDF2 的时间。
**嗯,在某种程度上确实很重要。请参阅 owlstead 对另一个答案的评论。它应该足够长以阻止彩虹表的使用。(尽管因为 PBKDF2 多次应用您的哈希函数,长盐并不像在传统的“直接哈希”应用程序中那么重要。)对于我的应用程序,我使用 32 字节随机盐,对于我所在的每个用户帐户都是唯一的用 PBKDF2 散列他们的密码。
希望有帮助!