我们使用PBKDF2算法使用SecretKeyFactory.generateSecret
函数散列密码,如下所示:
final SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algorithm);
final PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, iterations, hashLength);
final SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
return secretKey.getEncoded();
但是,在生产服务器上,一切似乎都运行良好,当它在IBM Java中运行时,它会以java.security.spec.InvalidKeySpecException
而死:无法生成密钥:
Caused by: java.security.spec.InvalidKeySpecException: Could not generate secret key
at javax.crypto.SecretKeyFactory.generateSecret(Unknown Source)
at our.Implementation.doHash(Hasher.java:71)
... 48 more
Caused by: java.lang.RuntimeException: Error deriving PBKDF2 keys
at com.ibm.crypto.provider.PBKDF2KeyImpl.a(Unknown Source)
at com.ibm.crypto.provider.PBKDF2KeyImpl.<init>(Unknown Source)
at com.ibm.crypto.provider.PBKDF2HmacSHA1Factory.engineGenerateSecret(Unknown Source)
... 50 more
我们尝试更改迭代次数,生成的哈希值和盐大小,但没有任何帮助。我做错了什么?
答案 0 :(得分:0)
显然,PBKDF2的IBM Java实现似乎坚持密码不能为空。如果是,则实现会抛出异常。
空密码可以说是一个边缘情况,但是,第一个测试用例就是这样,所以看起来代码根本不起作用。此外,在边缘情况下,您需要确保它永远不会发生(验证要求用户不要有空密码),或者您应该优雅地处理它。
如果你真的需要支持空密码,你需要将它们作为特殊情况处理,或者只是规范化所有密码,以便PBKDF2的输入永远不会为空。但是,您必须确保不会以这种方式破坏安全性。
最后,我们选择为所有密码添加长度前缀,以便即使空密码也以非空字符串表示。像那样:
final String prefixedPassword = String.format(Locale.ROOT, "%08x%s", password.length(), password);