Java SHA256 输出与 PHP SHA256 不同的哈希值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4680661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 07:29:37  来源:igfitidea点击:

Java SHA256 outputs different hash to PHP SHA256?

javaphphashsha256

提问by Finbarr

PHP code:

PHP代码:

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

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

PHP output:

PHP输出:

cdf30c6b345276278bedc7bcedd9d5582f5b8e0c1dd858f46ef4ea231f92731d

cdf30c6b345276278bedc7bcedd9d5582f5b8e0c1dd858f46ef4ea231f92731d

Java code:

爪哇代码:

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 output:

Java输出:

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

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

I had expected the two to return the same result. Obviously, this is not the case. How can I get the two to match up or is it impossible?

我原以为两者会返回相同的结果。显然,情况并非如此。我怎样才能让两者匹配或者是不可能的?

EDIT: I had made a mistake, think I have the answer to the question now anyway.

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

回答by Jon Skeet

Well, the very firstthing you need to do is use a consistent string encoding. I've no idea what PHP will do, but "jake".getBytes()will use whatever your platform default encoding is for Java. That's a really bad idea. Using UTF-8 would probably be a good start, assuming that PHP copes with Unicode strings to start with. (If it doesn't, you'll need to work out what it isdoing and try to make the two consistent.) In Java, use the overload of String.getBytes()which takes a Charsetor the one which takes the name of a Charset. (Personally I like to use Guava's Charsets.UTF_8.)

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

Then persuade PHP to use UTF-8 as well.

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

Then output the Java result in hex. I very much doubt that the code you've given is the actual code you're running, as otherwise I'd expect output such as "[B@e48e1b". Whatever you're doing to convert the byte array into a string, change it to use hex.

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

回答by mglauche

They are printing the same .. convert your byte[] to a hex string, then you'll see CDF30C6B345276278BEDC7BCEDD9D5582F5B8E0C1DD858F46EF4EA231F92731D as Java output, too:

他们正在打印相同的 .. 将您的 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();
}

回答by orlp

You need to convert the digest to a HEX string before printing it out. Example code can be found here.

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