5.2 PBKDF2
PBKDF2 应用伪随机函数 (pseudorandom function) (参见附录 B.1 的示例) 来派生密钥。派生密钥的长度本质上是无界的。(然而, 派生密钥的最大有效搜索空间可能受到底层伪随机函数的结构限制。参见附录 B.1 的进一步讨论。) 推荐 PBKDF2 用于新应用。
PBKDF2 (P, S, c, dkLen)
Options (选项): PRF - 底层伪随机函数 (hLen 表示伪随机函数输出的长度, 以八位字节为单位)
Input (输入):
- P - 密码, 八位字节串
- S - 盐值, 八位字节串
- c - 迭代次数, 正整数
- dkLen - 派生密钥的预期长度 (以八位字节为单位), 正整数, 最多为 (2^32 - 1) * hLen
Output (输出): DK - 派生密钥, dkLen 个八位字节的字符串
Steps (步骤):
-
如果 dkLen > (2^32 - 1) * hLen, 则输出 "derived key too long" (派生密钥太长) 并停止。
-
设 l 为派生密钥中 hLen 个八位字节块的数量, 向上取整, 设 r 为最后一个块中的八位字节数:
l = CEIL (dkLen / hLen)
r = dkLen - (l - 1) * hLen
其中, CEIL (x) 是 "ceiling" (向上取整) 函数, 即大于或等于 x 的最小整数。
- 对派生密钥的每个块, 将下面定义的函数 F 应用于密码 P、盐值 S、迭代次数 c 和块索引以计算块:
T_1 = F (P, S, c, 1)
T_2 = F (P, S, c, 2)
...
T_l = F (P, S, c, l)
其中函数 F 定义为底层伪随机函数 PRF 应用于密码 P 以及盐值 S 和块索引 i 的连接的前 c 次迭代的异或和:
F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
其中
U_1 = PRF (P, S || INT (i))
U_2 = PRF (P, U_1)
...
U_c = PRF (P, U_{c-1})
这里, INT (i) 是整数 i 的四个八位字节编码, 最高有效八位字节在前。
- 连接这些块并提取前 dkLen 个八位字节以产生派生密钥 DK:
DK = T_1 || T_2 || ... || T_l<0..r-1>
- 输出派生密钥 DK。
注意: 函数 F 的构造遵循 "belt-and-suspenders" (安全带和吊带) 方法。迭代 U_i 递归计算以消除对手的一定程度的并行性; 它们被异或在一起以减少对递归退化为小值集的担忧。