【问题标题】:Unable to reproduce Java MessageDigest hash in PHP无法在 PHP 中重现 Java MessageDigest 哈希
【发布时间】:2013-01-06 15:44:06
【问题描述】:

getHash(...) 方法中的 digest.update(salt) 在下面的代码示例中如何工作?我需要复制 PHP 中的逻辑。 testHash() 方法有一些嵌入的测试值。如果我注释掉digest.update(salt),我可以得到匹配。我在 PHP 中尝试了以下组合来获得匹配但没有运气(伪代码):

  • sha256($salt.$pass)
  • sha256($pass.$salt)
  • sha256($pass.sha256($salt))
  • sha256($salt.sha256($pass))
  • sha256(sha256($pass).sha256($salt))
  • sha256(sha256($salt).sha256($pass))

代码:

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class Owasp {

    private final static int ITERATION_NUMBER = 5;

    public void testhash() throws IOException, NoSuchAlgorithmException, UnsupportedEncodingException {
        byte[] bSalt = base64ToByte("123456");
        byte[] bDigest = getHash(ITERATION_NUMBER, "somepass", bSalt);
        String sDigest = byteToBase64(bDigest);
        System.out.println(sDigest);
    }

    public byte[] getHash(int iterationNb, String password, byte[] salt) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        digest.reset();
        digest.update(salt);
        byte[] input = digest.digest(password.getBytes("UTF-8"));
        for (int i = 0; i < iterationNb; i++) {
            digest.reset();
            input = digest.digest(input);
        }
        return input;
    }

    public static byte[] base64ToByte(String data) throws IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        return decoder.decodeBuffer(data);
    }

    public static String byteToBase64(byte[] data) {
        BASE64Encoder endecoder = new BASE64Encoder();
        return endecoder.encode(data);
    }

    public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException, IOException {
        Owasp t = new Owasp();
        t.testhash();
    }
}

编辑

我已经添加了我一直在使用的 PHP 代码。这并不理想,因为我没有列举我测试过的所有案例。使用我用 -g 编译的 rt.jar 文件单步调试 Netbeans 中的调试器,看起来它被存储为 $salt.$pass。使用 PHP 代码我无法找到匹配项。

PHP 代码:

<?php
//Without salt
$pass = "somepass";

$hash = hash('sha256', $pass, true);
for($i = 0; $i < 5; $i++) {
    $hash = hash('sha256', $hash, true);
}

echo "Java output without salt: " . "r+G0EnbjURjk99+wMvjnJV51d/tVX8tAn+7VAUCPXRY=" . "\n";
echo "PHP output without salt : " . base64_encode($hash) . "\n";


//With salt
$pass = "somepass";
$salt = "123456";

//I've tried all sorts of combinations and manipulation.
$hash = hash('sha256', $salt.$pass, true);
for($i = 0; $i < 5; $i++) {
    $hash = hash('sha256', $hash, true);
}

echo "Java output with salt: " . "vxZP4vmc+dixEhsZW58+zViLn7XXymirCP7kbl2KtT0=" . "\n";
echo "PHP output with salt : " . base64_encode($hash) . "\n";

更新

我已经用 Netbeans 中的调试器粘了几个小时了,现在试图弄清楚调用 digest.update($salt) 时发生了什么。 MessageDigestSPI 是关键。 engineUpdate(byte[] input, int offset, int len) 被调用,但我找不到实现。所有 engineUpdate 方法都可能指向engineUpdate(ByteBuffer input),但我无法确认。我以前做过 Java 工作,但那是几年前的事了。我已经尝试了每一个 hex2bin'ed、packed、unpacked 和 Base64'ed 的方法,但都没有运气:( 我会及时通知你们。

【问题讨论】:

  • 您能否发布删除digest.update(salt) 时有效的PHP 代码?
  • 你能发布你的完整 php 代码吗?你忘了 Base64 解码了吗?
  • @CodesInChaos:我希望就这么简单!
  • @Duncan Jones:我已经发布了 PHP。
  • 我希望像 Base64Decode($salt).$pass 这样的东西可以工作。

标签: java php hash cryptography


【解决方案1】:

算法基本上是hash(hash(hash(hash(...hash(password)...))))),由iterationNb参数指定的次数。

使用盐的正确方法是将其与密码连接起来,然后对其进行哈希处理。这是在您的代码中通过执行digest.update(salt),然后使用密码调用摘要来完成的。它本质上与以下内容相同:

  String saltedPassword = password + new String(salt, "UTF-8");
  byte[] input = digest.digest(saltedPassword.getBytes("UTF-8"));

当然,就像任何适当的盐一样,您需要将其与散列密码一起存储,以便将来能够验证它。

您可以获取有关 salt 如何存储密码哈希 at this Wikipedia link 的更多信息。此外,在this other StackOverflow question. 处存储密码时使用盐的一些最佳做法

【讨论】:

  • @CodesInChaos 是的,对不起,我一开始错过了。更新以反映这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-24
  • 2021-09-14
  • 2013-05-31
相关资源
最近更新 更多