在Java中使用HMAC的PBKDF2

时间:2013-11-08 15:22:43

标签: passwords java password-policy pbkdf2 hmac

我正在开发一个Java项目,我必须确保用户密码的机密性和完整性保存在纯文本文件中。

为此,我将只在文件中写入密码的哈希值。更具体地说,我的目的是编写密码的哈希值和随机盐,以及随机盐本身,以避免使用彩虹和查找表。我还想使用PBKDF2进行键拉伸,以使计算哈希计算成本高昂。 最后,我想使用密钥哈希算法HMAC作为最后一层保护。

我正在尝试用Java代码实现我的想法,并且我已经找到了一些上面提到的操作示例:

private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes)
    throws NoSuchAlgorithmException, InvalidKeySpecException
{
    PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8);
    SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    return skf.generateSecret(spec).getEncoded();
}

我真正无法理解的是如何输入我的密钥作为HMAC算法使用的密钥,因为它似乎不是函数的输入。我查看了Java文档,但是我无法找到解决问题的方法。

此时,我不确定我是否正确理解加密机制的不同部分是如何工作的,所以我会接受有关该主题的任何帮助。

1 个答案:

答案 0 :(得分:11)

我想我看到了混乱。您显然希望您的代码应用PBKDF2然后HMAC-SHA-1。这不是它的工作原理:在PBKDF2中使用HMAC-SHA-1。

PBKDF2的要点是重复应用具有以下属性的函数:

  • 它需要两个参数;
  • 返回固定大小的值;
  • 实际上与伪随机函数无法区分。

HMAC-SHA-1就是这样一种功能,也是一种常见的选择。 PBKDF2还有其他变体,使用HMAC-MD5,HMAC-SHA-256或其他功能(但这些变体不在基本Java库中)。

PBKDF2需要两个数据输入(加上一些配置输入):密码和盐。如果你想在计算中包含一个秘密值,那么PBKDF2的输入就是它的位置:不要在自定义方案上使用(做你自己的加密是做错的一个秘诀)。将pepper(所有帐户共有的秘密值)附加到salt(帐户之间的公共值不同)。

请注意pepper is of limited usefulness。仅当散列和胡椒秘密值存储在不同的位置时才有用 - 例如,如果散列位于数据库中且胡椒位于不直接易受SQL注入攻击的磁盘文件中。