带有盐的SHA-512在Java和PHP之间不匹配

时间:2018-06-21 09:02:37

标签: java php hash sha512

我的应用程序在Java中使用了盐腌哈希。首先,生成随机盐。然后将这个盐前缀为输入密码的SHA-512,组合的字符串再次为SHA-512,其实现方式如下:-

String password = testpwd.getText().toString();
SecureRandom rand = new SecureRandom();
byte[] randbytes = new byte[16];
rand.nextBytes(randbytes);
String encodedSalt = Base64.encodeToString(randbytes, Base64.DEFAULT);

MessageDigest digest = MessageDigest.getInstance("SHA-512");
digest.reset();
digest.update(password.getBytes("utf-8"));
byte[] pwdhash = digest.digest();
String encodedPwd = Base64.encodeToString(pwdhash, Base64.DEFAULT);

String saltedPassword = encodedSalt+encodedPwd ;

digest.reset();
digest.update(saltedPassword.getBytes("utf-8"));
byte[] pwdhash1 = digest.digest();
String encodedPwdSalt = Base64.encodeToString(pwdhash1, Base64.DEFAULT);

然后,将字符串encodeSalt和encodePwdSalt发送到Web服务器进行身份验证。 PHP加密如下:

$postpassword = $_POST['password'];
$postsalt = $_POST['salt'];
$salt = base64_decode($postsalt);
$password = base64_decode('postpassword');

密码“ Ditglt @ 785”的SHA-512哈希存储在数据库中。它的检索和处理如下:-

$getsaltpwd = $salt.$dbpassword ;
$dbsaltpwd = hash('sha512', $getsaltpwd);
if($dbpassword == $postpassword) {}

条件始终失败,因此身份验证也失败。我该怎么办?

3 个答案:

答案 0 :(得分:2)

PHP版本对 raw 字节进行哈希处理,而Java版本对 base64编码的字符串进行哈希处理。

以下是与您的PHP代码匹配的Java版本:

digest.reset();
digest.update(randbytes);
digest.update(pwdhash);
byte[] pwdhash1 = digest.digest();
String encodedPwdSalt = Base64.encodeToString(pwdhash1, Base64.DEFAULT);

话虽如此,将 salt saltted密码存储在数据库中,并至少使用一些key derivation function(多次对哈希函数进行迭代),以抵消所存储哈希的任何潜在的暴力破解。

答案 1 :(得分:1)

由于Java代码正确地遵循了规范中的描述,因此问题出在PHP端。

照原样使用Java代码,当使用随机盐对字符串“ password”进行编码时,它将生成以下值:

encodedSalt: ww0g+f77ygKD7Iww1GTYtg==
encodedPwd: sQnzu7wkTrgkQZF+0G1hi5AI3Qmzvv0bXgc5THBqi7mAsdd4Xll27ASbRt9fEyavWi6m0QP9B8lThf+rDKy8hg==
encodedPwdSalt: YAGG7GcpUxIZzBnHuaezPf5BWFhFalBPgvue/0wFoRLu+JsKslG8wPCv6dPubIBk1aFIJ8spK8S17347aDBAYA==

在PHP中,您需要执行以下操作:

$postpassword = 'YAGG7GcpUxIZzBnHuaezPf5BWFhFalBPgvue/0wFoRLu+JsKslG8wPCv6dPubIBk1aFIJ8spK8S17347aDBAYA==';
$postsalt = 'ww0g+f77ygKD7Iww1GTYtg==';
$dbpassword = 'sQnzu7wkTrgkQZF+0G1hi5AI3Qmzvv0bXgc5THBqi7mAsdd4Xll27ASbRt9fEyavWi6m0QP9B8lThf+rDKy8hg==';

if($postpassword == base64_encode(hash('sha512', $postsalt.$dbpassword, true))) {
    echo 'OK';
}  

答案 2 :(得分:0)

检查填充是否匹配。我在加密中遇到了相同的问题,其中PHP中的填充与JAVA中的填充不同。幸运的是,我能够将JAVA中的填充设置为PHP使用的填充。但是我必须查看PHP源代码才能弄清楚如何做。据我所知,当时无法更改PHP中的填充。

这是我当时发布的问题:decrypting php encrypted data on android

  

[...]您需要使用参数Base64.NO_WRAP设置Base64.decode,因为PHP只会输出以\ 0分隔的base64。