在互联网存储用户密码时,为了安全起见,不能采用明文储存的方式,而需要对其进行Hash,得到Hash值后进行保存。但这种方法很容易受到彩虹表攻击,于是便出现了Hash+salt(哈希+盐值)的操作。今天我们就来了解一种重复多次Hash+salt操作的算法——PBKDF2算法。

PBKDF2算法简介

PBKDF2(Password-Based Key Derivation Function 2)是应用一个伪随机函数以导出密钥,导出密钥的长度本质上是没有限制的,但导出密钥的最大有效搜索空间受限于基本伪随机函数的结构。

PBKDF2的原来是通过一个伪随机函数,把明文和一个盐值作为输入参数,然后重复进行运算,并最终产生密钥。

简单来说,就是在Hash算法基础上增加随机盐,并进行多次Hash运算,随机盐使得彩虹表的建表难度大幅增加,而多次Hash也使得建表和破解的难度都大幅增加。

PBKDF2

PBKDF2算法过程

首先,我们先来了解一个函数,DK=PBKDF2(PRF, Password, Salt, c, dkLen)。其中:

  1. DK是PBKDF2算法产生的密钥
  2. PRF是一个伪随机函数,例如HASH_HMAC函数,它会输出长度为hLen的结果
  3. Password 是用来生成密钥的原文密码
  4. Salt 是一系列用于生成密钥加密的盐值
  5. c是迭代运算的次数
  6. dkLen 是期望得到的密钥的长度

PBKDF2

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)

PBKDF2算法的安全性

使用PBKDF2算法时,Hash算法一般选用sha1或者sha256,随机盐的长度一般不能少于8字节,Hash次数至少也要1000次,这样安全性才足够高。一次密码验证过程进行1000次Hash运算,对服务器来说可能只需要1ms,但对于破解者来说计算成本增加了1000倍,而至少8字节随机盐,更是把建表难度提升了N个数量级,使得大批量的破解密码几乎不可行,该算法也是美国国家标准与技术研究院推荐使用的算法。

免责声明:素材源于网络,如有侵权,请联系删稿。