慢哈希算法
1.PBKDF算法
PBKDF2应用一个伪随机函数以导出密钥。导出密钥的长度本质上是没有限制的(但是,导出密钥的最大有效搜索空间受限于基本伪随机函数的结构)。
PBKDF2,PBKDF2简单而言就是将salted hash进行多次重复计算,这个次数是可选择的。如果计算一次所需要的时间是1微秒,那么计算1百万次就需要1秒钟。假如攻击一个密码所需的rainbow table有1千万条,建立所对应的rainbow table所需要的时间就是115天。这个代价足以让大部分的攻击者望而生畏。
1.1PBKDF算法函数定义:
DK = PBKDF2(PRF, Password, Salt, c, dkLen)
其中:
- 1.DK是PBKDF2算法产生的密钥
- 2.PRF是一个伪随机函数,例如HASH_HMAC函数,它会输出长度为hLen的结果
- 3.Password 是用来生成密钥的原文密码
- 4.Salt 是一系列用于生成密钥加密的盐值
- 5.c是迭代运算的次数
- 6.dkLen 是期望得到的密钥的长度
1.2.PBKDF算法流程:
DK的值由一个以上的block拼接而成。block的数量是dkLen/hLen的值。就是说如果PRF输出的结果比期望得到的密钥长度要短,则要通过拼接多个结果以满足密钥的长度:
DK = T1 || T2 || ... || Tdklen/hlen
而每个block则通过则通过函数F得到:
Ti = F(Password, Salt, c, i)
在函数F里,PRF会进行c次的运算,然后把得到的结果进行异或运算,得到最终的值。
F(Password, Salt, c, i) = U1 ^ U2 ^ ... ^ Uc
第一次,PRF会使用Password作为key,Salt拼接上编码成大字节序的32位整型的i作为盐值进行运算。
U1 = PRF(Password, Salt || INT_32_BE(i))
而后续的c-1次则会使用上次得到的结果作为盐值。
U2 = PRF(Password, U1)
...
Uc = PRF(Password, Uc-1)
伪代码:
PBKDF(Password,Salt,c,dkLen)
{
r=dkLen/hLen;
for i=1 to c;
T=hmac(Password,Salt||i)
U=T
for j=1 to c;
T=hmac(Password,T)
U=U U=U ⊕ T
out out || U
return out[0:dkLen] //out[0:dKlen]表示输出取out数组的前dKlen位
}
2.Scrypt算法:
Scrypt密码哈希的安全性要高于Bcrypt,Scrypt内部还使用了PBKDF2算法。
3.Argon2算法:
Argon2的入参和Scrypt差不多