哪个 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
Which SHA-256 is correct? The Java SHA-256 digest or the Linux commandline tool
提问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));

