【问题标题】:SHA-512 with salt not matching between Java and PHP带有盐的 SHA-512 在 Java 和 PHP 之间不匹配
【发布时间】:2018-06-21 09:02:37
【问题描述】:

我的应用程序在 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);

然后字符串encodedSalt和encodedPwdSalt被发送到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) {}

条件总是失败,身份验证也是如此。我该怎么办?

【问题讨论】:

  • $postpassword比较时,您不应该使用$dbsaltpwd而不是$dbpassword吗?
  • base64_decode('postpassword'); 在你的第一个 PHP 块中做什么? (为什么要解码常量?)
  • 你也不应该在 PHP 中对你的 salt 进行 base64 解码,因为你在 Java 中对一个 base64 编码的 salt 进行哈希处理。
  • @John 您应该更具体地了解您想要的编码/合并/哈希步骤的过程。 Java 和 PHP 之间显然存在不匹配,我们只能猜测哪个进程是预期的。
  • @RobbyCornelissen 你是对的“使用 $dbsaltpwd 而不是 $dbpassword”。但是在这里发布问题时这是一个错字。在代码中就像你提到的那样。

标签: java php hash sha512


【解决方案1】:

PHP 版本散列 原始 字节,而 Java 版本散列 base64 编码 字符串。

这是一个与您的 PHP 代码相匹配的 Java 版本:

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

话虽如此,将 saltsalted 密码 存储在数据库中会更安全,并且至少使用一些 key derivation function(迭代哈希函数多次),以抵消存储哈希的任何潜在暴力破解。

【讨论】:

  • 哦!我使用了 String saltedPassword = encodedSalt+encodedPwd 行;实现这一目标
  • Java 版本正在散列saltedPassword,大致是encode(salt) + encode(hash(password))(这不是Java 语法)。也许$salt 不应该通过base64_decode 传递,因为他们似乎想要散列编码 salt。
  • saltedPassword = encodedSalt+encodedPwd;不正确。
【解决方案2】:

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

使用您的 Java 代码,当使用随机盐对字符串“密码”进行编码时,它会生成以下值:

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';
}  

【讨论】:

  • 你说我的Java代码原样,但根据rustyx,saltedPassword = encodedSalt+encodedPwd 部分不正确。
  • 没有什么不对的地方。您选择连接两个 base64 编码的字符串并对其进行哈希处理,而他选择连接两个字节数组并对其进行哈希处理。结果显然会有所不同,但其中一个并不比另一个更正确。
【解决方案3】:

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

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

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

【讨论】:

  • SHA-512?填充?
  • @RobbyCornelissen 我再次查看了我的问题,Base64 的问题是分隔字符。
猜你喜欢
  • 1970-01-01
  • 2014-05-12
  • 2014-11-11
  • 2013-02-01
  • 1970-01-01
  • 2018-11-04
  • 2019-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多