在 Java 和 PHP 中使用 PBKDF2
Using PBKDF2 in Java and PHP
我在 Java 和 PHP 上使用 PBKDF2 算法生成相同的加密密码时遇到一些困难。
我正在使用以下 Java 实现来生成具有 16 字节大小的随机字节数组的散列。然后我将散列和盐分别存储在 MySQL 数据库中,但是当我使用从数据库中检索到的盐在 PHP 中执行相同的操作时,我得到几乎完全相同的加密,除了哈希有一个前导 0,我终究无法弄清楚为什么。
Java:
public String hashPassword(String password, byte[] salt){
char[] passwordChars = password.toCharArray();
PBEKeySpec spec = new PBEKeySpec(
passwordChars,
salt,
ITERATIONS,
KEY_LENGTH
);
SecretKeyFactory key = null;
try {
key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte[] hashedPassword = null;
try {
hashedPassword = key.generateSecret(spec).getEncoded();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return String.format("%x", new BigInteger(hashedPassword));
}
我在https://adambard.com/blog/3-wrong-ways-to-store-a-password/
找到了上面的代码
PHP:
$query = $database->query('SELECT * FROM USERS');
$password = 'hello';
$iterations = 1000;
foreach($query as $user){
$hash = hash_pbkdf2("sha1", $password, $user['salt'], $iterations, 40, false);
}
echo $hash;
注意:数据库中只存储了一个用户,我知道上面的代码不是很好,为了测试目的我很快创建了它。
对于这两种实现,我使用的迭代计数为 1000,Java 中的密钥长度为 160,PHP 中的密钥长度为 40(以补偿将原始输出设置为假)
Java Output - 971f0dddc1bc2e899f2bca178f16ea79bfbbb13
PHP Output - 0971f0dddc1bc2e899f2bca178f16ea79bfbbb13
非常感谢任何帮助,谢谢。
杀死前导0的是BigInteger
。
哈希不是整数,它们是 8 位字节的数组。不要尝试转换为 BigInteger
.
将其用作 byte[]
或编码为十六进制或 Base64 字符串。匹配 PHP 十六进制编码 hashedPassword
.
PHP 返回十六进制字符串编码哈希,因为 raw_output
设置为 FALSE
。
我在 Java 和 PHP 上使用 PBKDF2 算法生成相同的加密密码时遇到一些困难。
我正在使用以下 Java 实现来生成具有 16 字节大小的随机字节数组的散列。然后我将散列和盐分别存储在 MySQL 数据库中,但是当我使用从数据库中检索到的盐在 PHP 中执行相同的操作时,我得到几乎完全相同的加密,除了哈希有一个前导 0,我终究无法弄清楚为什么。
Java:
public String hashPassword(String password, byte[] salt){
char[] passwordChars = password.toCharArray();
PBEKeySpec spec = new PBEKeySpec(
passwordChars,
salt,
ITERATIONS,
KEY_LENGTH
);
SecretKeyFactory key = null;
try {
key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte[] hashedPassword = null;
try {
hashedPassword = key.generateSecret(spec).getEncoded();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return String.format("%x", new BigInteger(hashedPassword));
}
我在https://adambard.com/blog/3-wrong-ways-to-store-a-password/
找到了上面的代码PHP:
$query = $database->query('SELECT * FROM USERS');
$password = 'hello';
$iterations = 1000;
foreach($query as $user){
$hash = hash_pbkdf2("sha1", $password, $user['salt'], $iterations, 40, false);
}
echo $hash;
注意:数据库中只存储了一个用户,我知道上面的代码不是很好,为了测试目的我很快创建了它。
对于这两种实现,我使用的迭代计数为 1000,Java 中的密钥长度为 160,PHP 中的密钥长度为 40(以补偿将原始输出设置为假)
Java Output - 971f0dddc1bc2e899f2bca178f16ea79bfbbb13
PHP Output - 0971f0dddc1bc2e899f2bca178f16ea79bfbbb13
非常感谢任何帮助,谢谢。
杀死前导0的是BigInteger
。
哈希不是整数,它们是 8 位字节的数组。不要尝试转换为 BigInteger
.
将其用作 byte[]
或编码为十六进制或 Base64 字符串。匹配 PHP 十六进制编码 hashedPassword
.
PHP 返回十六进制字符串编码哈希,因为 raw_output
设置为 FALSE
。