我的应用程序在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) {}
条件总是失败,身份验证也是如此。 我该怎么办 ?
与$postpassword进行比较时,是否应该使用$dbsaltpwd而不是$dbpassword?
base64_decode(postpassword);在您的第一个PHP块中做什么? (为什么要解码常量?)
您不应该在PHP中使用base64解码盐,因为您在Java中哈希了以base64编码的盐。
@John您应该更具体地了解所需的编码/ concat /哈希步骤的过程。 Java和PHP之间显然不匹配,只能猜测哪个过程是预期的。
@RobbyCornelissen您对"使用$ dbsaltpwd而不是$ dbpassword"是正确的。但这是在此处发布问题时的错字。正如您提到的那样,在代码中。
默认情况下,PHP hash()返回的hexits与base64编码的字符串相比。很抱歉,但是您的实现感觉有点像冰雹玛丽的尝试。检查整个过程中的每个步骤,您应该可以弄清楚。
@RobbyCornelissen但是我在比较之前已经使用base64解码了密码。 $ password = base64_decode(postpassword);
但是,您将其与$postpassword而不是与$password进行比较。而且,即使您与$password进行比较,您仍将十六进制与二进制数据进行比较。
好,谢谢。那我应该如何比较十六进制和二进制数据呢?
PHP版本对原始字节进行哈希处理,而Java版本对base64编码的字符串进行哈希处理。
这是与您的PHP代码相匹配的Java版本:
digest.reset();
digest.update(randbytes);
digest.update(pwdhash);
byte[] pwdhash1 = digest.digest();
String encodedPwdSalt=Base64.encodeToString(pwdhash1, Base64.DEFAULT);
话虽如此,将盐和盐分的密码存储在数据库中,并至少使用一些密钥派生函数(多次迭代哈希函数)以抵消所存储的任何潜在的暴力行为,这将更加安全。哈希。
哦! 我使用了String saltedPassword = encodeSalt + encodedPwd行; 为达到这个
Java版本正在对saltedPassword进行哈希处理,即encode(salt) + encode(hash(password)),大致来说(不是Java语法)。 也许$salt不应该通过base64_decode传递,因为他们似乎想散列编码的盐。
saltedPassword = encodeSalt + encodedPwd; 是不正确的。
由于您的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';
}
谢谢。 我正在尝试
您已经说了我的Java代码,但是根据rustyx的说法,saltedPassword = encodeSalt + encodedPwd部分不正确。
没有什么不对的。 您选择串联两个base64编码的字符串并对其进行哈希处理,而他选择串联两个字节数组并对其进行哈希处理。 结果显然会有所不同,但是一个并不比另一个更正确。
非常感谢@Robby。 我正在将您的答案标记为已接受
检查填充是否匹配。我在加密中遇到了相同的问题,其中PHP中的填充与JAVA中的填充不同。幸运的是,我能够将JAVA中的填充设置为PHP使用的填充。但是我必须查看PHP源代码才能弄清楚如何做。据我所知,当时无法更改PHP中的填充。
这是我当时发布的问题:在android上解密php加密数据
[...] you need to set Base64.decode with the parameter Base64.NO_WRAPas PHP will just put out the base64 delimited by \0.
SHA-512? 填充?
@RobbyCornelissen我从那以后再次看了我的问题,而Base64的问题是定界字符。