简体   繁体   English

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

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

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 -n to not add a newline) : 在命令行上我执行以下操作(我需要-n不添加换行符):

echo -n "password" | sha256sum

and get 得到

5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

if we compare these more closely I find 2 subtle differences 如果我们更仔细地比较这些,我会发现两个微妙的差异

5e884898da2847151d0e56f8dc6292773603dd6aabbdd62a11ef721d1542d8
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

or : 要么 :

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

Which of the 2 is correct here? 这两个中哪一个是正确的?

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! 谢谢!

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

The culprit is the toHexString . 罪魁祸首是toHexString It appears to be outputting 6 for the value 6 whereas the sha256sum one is outputting 06 . 它似乎是输出值6为6,而sha256sum输出06 The Java docs for Integer.toHexString() state: 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 (eg, 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));
}

它们都是正确的 - 这是你的Java代码有问题,因为它不会为小于0x10的十六进制值打印出前导0。

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

The one generated by sha256sum seems correct. sha256sum生成的那个似乎是正确的。 Your implementation seems to drop those two zeroes. 你的实现似乎放弃了这两个零。

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 Owen answer. 并阅读@Sean Owen的回答。

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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM