10

PHP代码:

echo hash('sha256', 'jake');

PHP 输出:

cdf30c6b345276278bedc7bcedd9d5582f5b8e0c1dd858f46ef4ea231f92731d

Java代码:

String s = "jake";
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(s.getBytes(Charset.forName("UTF-8")));
byte[] hashed = md.digest();
String s2 = "";
for (byte b : hashed) {
    s2 += b;
}
System.out.println(s2);

Java 输出:

-51-1312107528211839-117-19-57-68-19-39-43884791-1141229-4088-12110-12-223531-11011529

我曾期望两者返回相同的结果。显然,事实并非如此。我怎样才能让两者匹配或不可能?

编辑:我犯了一个错误,我想我现在已经有了问题的答案。

4

3 回答 3

13

那么,您需要做的第一件事就是使用一致的字符串编码。我不知道 PHP 会做什么,但"jake".getBytes()会使用您的平台默认编码用于 Java。这真是个坏主意。假设 PHP 从一开始就处理 Unicode 字符串,那么使用 UTF-8 可能是一个好的开始。(如果没有,您需要弄清楚它做什么,并尝试使两者保持一致。)在 Java 中,使用采用 a 的重载或String.getBytes()采用 aCharset名称的重载Charset。(我个人喜欢使用 Guava 的Charsets.UTF_8。)

然后说服 PHP 也使用 UTF-8。

然后以十六进制输出 Java 结果。我非常怀疑您给出的代码是您正在运行的实际代码,否则我希望输出诸如“[B@e48e1b”。无论您正在做什么将字节数组转换为字符串,请将其更改为使用十六进制。

于 2011-01-13T13:44:17.003 回答
6

他们正在打印相同的 .. 将您的 byte[] 转换为十六进制字符串,然后您也会看到 CDF30C6B345276278BEDC7BCEDD9D5582F5B8E0C1DD858F46EF4EA231F92731D 作为 Java 输出:

public void testSomething() throws Exception {
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update("jake".getBytes());
    System.out.println(getHex(md.digest()));
}

static final String HEXES = "0123456789ABCDEF";
public static String getHex( byte [] raw ) {
    if ( raw == null ) {
      return null;
    }
    final StringBuilder hex = new StringBuilder( 2 * raw.length );
    for ( final byte b : raw ) {
      hex.append(HEXES.charAt((b & 0xF0) >> 4))
         .append(HEXES.charAt((b & 0x0F)));
    }
    return hex.toString();
}
于 2011-01-13T13:50:19.513 回答
2

您需要将摘要转换为十六进制字符串,然后再将其打印出来。示例代码可以在这里找到。

于 2011-01-13T13:44:31.653 回答