我正在将一个Web应用程序从Ruby移植到Java,并希望允许用户在不重置密码的情况下登录.以下是使用pbkdf2 gem生成哈希的Ruby代码:
PBKDF2.new { |p|
p.password = password
p.salt = salt
p.iterations = 10000
}.hex_string
Run Code Online (Sandbox Code Playgroud)
读取Ruby gem的源代码,它使用OpenSSL :: Digest.new("sha256")作为默认的散列函数,并生成一个32字节的值,使用'unpack("H*")转换为64个字符的字符串)".
所以,在Java中我尝试了以下内容:
public String generatePasswordHash(String password, String salt) throws NoSuchAlgorithmException, InvalidKeySpecException
{
char[] chars = password.toCharArray();
byte[] saltBytes =salt.getBytes();
PBEKeySpec spec = new PBEKeySpec(chars, saltBytes, 1000, 256);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = skf.generateSecret(spec).getEncoded();
BigInteger bi = new BigInteger(1, hash);
return bi.toString(16);
}
Run Code Online (Sandbox Code Playgroud)
使用password ="apassword"和salt ="somesalt"测试两段代码,我得到以下结果.
Ruby: 3fa1eb7544ca49b1f371eb17d24bf0010c433fa263a84aff7df446741371706b
Java: 77a7c0b1ea9760d0b1ef02e7a2633c40ccd7848ee4fa822ec71b5794e476f354
Run Code Online (Sandbox Code Playgroud)
我测试了Ruby和Java十六进制字符串编码,它们的工作方式相同,因此问题看起来是在散列算法中,或者可能是字符串转换为字节数组的方式.