[英]pbkdf2 pkcs5 compatible hashing in Java, PHP and Objective-C
I'm developing an app that requires pbkdf2 pkcs5 for password hashing. 我正在开发一个需要pbkdf2 pkcs5进行密码哈希处理的应用程序。 I think I have some working code in PHP & Java but I'm not sure why they are producing different results.
我想我在PHP和Java中有一些有效的代码,但是我不确定为什么它们会产生不同的结果。
Here are the code. 这是代码。
Php code: 邮递区号:
function hash_password($password, $salt, $user_id, $iterations) {
$user_id = (string) $user_id;
$raw_pass = $salt . $user_id . $password;
$hash = hash_pbkdf2("sha512", $raw_pass, $salt, $iterations, 64, false);
return $hash;
}
echo hash_password("password", $salt, 2058, 1);
echo PHP_EOL;
Java code: Java代码:
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.nio.charset.StandardCharsets;
import java.lang.RuntimeException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.math.BigInteger;
import javax.xml.bind.DatatypeConverter;
public final class Testing {
private static String mSalt = "fd6c3dc0165dc420b4e9225bc9bee9684387e9621b2e2c00cfffebf1ec7c30b4";
private static String hashPassword(String password, String salt, int userId, int iterations) throws RuntimeException {
String uid = String.valueOf(userId);
StringBuilder pwBuilder = new StringBuilder(salt);
pwBuilder.append(uid);
pwBuilder.append(password);
String rawPass = pwBuilder.toString();
try {
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), mSalt.getBytes(), iterations, 256);
byte[] result = skf.generateSecret(spec).getEncoded();
StringBuilder hashBuilder = new StringBuilder(result.length * 2);
for (byte r : result) {
hashBuilder.append(String.format("%02x", r));
}
return hashBuilder.toString();
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new RuntimeException( e );
}
}
public static void main(String[] args) {
System.out.println(hashPassword("password", mSalt, 2058, 1000000));
System.out.println("\n");
}
}
Php output is: 3754036ea2f37af8160e45d15c2e4d6597157ead118f060e76152c0813f806e8
PHP输出是:
3754036ea2f37af8160e45d15c2e4d6597157ead118f060e76152c0813f806e8
Java output is: 8b135bb19263677b70f1d5cbda5a23bc16df38e5e1a624c6df9a462975cac899
Java输出是:
8b135bb19263677b70f1d5cbda5a23bc16df38e5e1a624c6df9a462975cac899
Can you recommend a library or a gist somewhere that has both compatible implementation? 您可以在兼具兼容实现的地方推荐一个库或要点吗?
You have two issues with your existing code: 您现有的代码有两个问题:
Use the same number of iterations. 使用相同的迭代次数。
Use the same concatenated password. 使用相同的串联密码。
In PHP: 在PHP中:
Use 采用
var_dump(hash_password("password", $salt, 2058,
1000000));
instead of 代替
var_dump(hash_password("password", $salt, 2058,
1));
In Java: 在Java中:
Use 采用
PBEKeySpec spec = new PBEKeySpec(
rawPass.toCharArray(), mSalt.getBytes(), iterations, 256);
instead of 代替
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(), mSalt.getBytes(), iterations, 256);
After you've made those changes, both will produce the same result: 进行这些更改之后,两者都会产生相同的结果:
424a0b30ea0cdef2ff0185f49ce67ee44273ce7e41026044d527c85550b3a207
Never use String#getBytes
without a specific character set. 切勿
String#getBytes
没有特定字符集的情况下使用String#getBytes
。 Otherwise, the system default will be used which can be different in different JVM's. 否则,将使用系统默认值,该默认值在不同的JVM中可能会有所不同。
If you're using PBKDF2 to hash passwords, then you will need to compare two hashes when verifying the re-entered password. 如果您使用PBKDF2对密码进行哈希处理,则在验证重新输入的密码时需要比较两个哈希值。 This requires a constant-time comparison function to prevent timing-based attacks.
这需要恒定时间比较功能以防止基于定时的攻击。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.