哪个 SHA-256 是正确的?Java SHA-256 摘要或 Linux 命令行工具

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3021970/
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-29 23:59:22  来源:igfitidea点击:

Which SHA-256 is correct? The Java SHA-256 digest or the Linux commandline tool

javasecurityhash

提问by Peter Tillemans

When I calculate in Java an SHA-256 of a string with the following method

当我在 Java 中使用以下方法计算字符串的 SHA-256 时

public static void main(String[] args) throws NoSuchAlgorithmException {

    MessageDigest md = MessageDigest.getInstance("SHA-256");

    byte[] hash = md.digest("password".getBytes());

    StringBuffer sb = new StringBuffer();
    for(byte b : hash) {
        sb.append(Integer.toHexString(b & 0xff));
    }

    System.out.println(sb.toString());
}

I get :

我得到:

5e884898da2847151d0e56f8dc6292773603dd6aabbdd62a11ef721d1542d8

on the commandline I do the following (I need the -nto not add a newline) :

在命令行上,我执行以下操作(我需要-n不添加换行符):

echo -n "password" | sha256sum

and get

并得到

5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

if we compare these more closely I find 2 subtle differences

如果我们更仔细地比较这些,我会发现 2 个细微的差异

5e884898da2847151d0e56f8dc6292773603dd6aabbdd62a11ef721d1542d8
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

or :

或者 :

5e884898da28   47151d0e56f8dc6292773603d   d6aabbdd62a11ef721d1542d8
5e884898da28 0 47151d0e56f8dc6292773603d 0 d6aabbdd62a11ef721d1542d8

Which of the 2 is correct here?

2 中哪一个是正确的?

Result:Both are but I was wrong...

结果:两者都是,但我错了......

fixed it by using :

使用以下方法修复它:

    StringBuffer sb = new StringBuffer();
    for(byte b : hash) {
        sb.append(String.format("%02x", b));
    }

Thanks!

谢谢!

回答by Sean Owen

I'll take a reasonable guess: both are outputting the same digest, but in your Java code that outputs the byte[]result as a hex string, you outputting small byte values (less than 16) without a leading 0. So a byte with value "0x0d" is being written as "d" not "0d".

我会做出一个合理的猜测:两者都输出相同的摘要,但是在将byte[]结果输出为十六进制字符串的Java 代码中,您输出的是没有前导 0 的小字节值(小于 16)。所以一个带有值的字节“ 0x0d”被写为“d”而不是“0d”。

回答by paxdiablo

The culprit is the toHexString. It appears to be outputting 6for the value 6 whereas the sha256sumone is outputting 06. The Java docs for Integer.toHexString()state:

罪魁祸首是toHexString. 它似乎在输出6值 6 而sha256sum一个正在输出06. Integer.toHexString()状态的 Java 文档:

This value is converted to a string of ASCII digits in hexadecimal (base 16) with no extra leading 0s.

该值被转换为十六进制(基数为 16)的 ASCII 数字字符串,没有额外的前导 0。

The other zeros in the string aren't being affected since they're the second half of the bytes (e.g., 30).

字符串中的其他零不受影响,因为它们是字节的后半部分(例如,30)。

One way to fix it would be to change:

修复它的一种方法是更改​​:

for(byte b : hash) {
    sb.append(Integer.toHexString(b & 0xff));
}

to:

到:

for(byte b : hash) {
    if (b < 16) sb.append("0");
    sb.append(Integer.toHexString(b & 0xff));
}

回答by David M

They're both right - it's your Java code that is at fault, because it is not printing out the leading 0 for a hex value less than 0x10.

他们都是对的——是你的 Java 代码有问题,因为它没有打印出小于 0x10 的十六进制值的前导 0。

回答by yegong

You still need "echo -n" to prevent the trailing \n

您仍然需要“echo -n”来防止尾随 \n

回答by yegong

The one generated by sha256sum seems correct. Your implementation seems to drop those two zeroes.

sha256sum 生成的那个似乎是正确的。您的实现似乎删除了这两个零。

回答by lpinto.eu

Using @paxdiablo idea had problem with big number as it appear as negative, so

使用@paxdiablo 的想法有大数字的问题,因为它显示为负数,所以

Instead of:

代替:

for(byte b : hash) {
    sb.append(Integer.toHexString(b & 0xff));
}

you could do:

你可以这样做:

for(byte b : hash) {
    if (b > 0 && b < 16) {
        sb.append("0");
    }
    sb.append(Integer.toHexString(b & 0xff));
}

And read @Sean Owenanswer.

并阅读@Sean Owen 的回答。

回答by gswierczynski

You can also get the right result using this:

您还可以使用以下方法获得正确的结果:

MessageDigest md = MessageDigest.getInstance("SHA-256");

byte[] hash = md.digest("password".getBytes());

BigInteger bI = new BigInteger(1, hash);

System.out.println(bI.toString(16));