在 java 中使用 SHA-256 散列十六进制数

Hash a hexadecimal number using SHA-256 in java

我在 Java 中编写了一个使用 SHA-256 散列十六进制数的代码。请看我的代码。

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Test {
    
    public static void main (String[] args) throws NoSuchAlgorithmException {
        
        BigInteger x = new BigInteger("f35b", 16);
        
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(x.byteValue());
        byte[] hashedXArray = md.digest();
        
        BigInteger hashedX = new BigInteger(hashedXArray);
        System.out.println(hashedX.toString(16));
        
    }
    
}

它的结果是……

245843abef9e72e7efac30138a994bf6301e7e1d7d7042a33d42e863d2638811

然后我使用另一个带有 SHA-256 的第三方应用程序对相同的输入进行哈希处理。它的答案与上面的输出完全不同。这是...

cd05094b5c5a5b80386da4fcfdd20e6ef5d363d97834ac8705e9832e6bd97f39

我还是不明白为什么我的代码结果与十六进制“f35b”的sha256的实际值相差很大,我该如何解析我的代码?

不使用 BigInteger:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;

public class HashIt {

    public static void main(String[] args) throws NoSuchAlgorithmException {
        byte[] input = new byte[] { (byte) 0xf3, (byte) 0x5b };
        System.out.println(toHexString(input));
        
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(input);
        byte[] hashedXArray = md.digest();
        
        System.out.println(toHexString(hashedXArray));
    }
    
    private static String toHexString(byte[] bytes) {
        Formatter result = new Formatter();
        try (result) {
            for (var b : bytes) {
                result.format("%02x", b & 0xff);
            }
            return result.toString();
        }
    }
}

输出:

f35b
cd05094b5c5a5b80386da4fcfdd20e6ef5d363d97834ac8705e9832e6bd97f39


如果输入必须为字符串,添加:

    private static byte[] fromHexString(String text) {
        assert text.length()%2 == 0 : "invalid text length";
        
        byte[] result = new byte[text.length()/2];
        for (int i = 0;  i < text.length(); i += 2) {
            result[i/2] = (byte) Integer.parseInt(text.substring(i, i+2), 16);
        }
        return result;
    }

并调用 byte[] input = fromHexString("f35b");

只是众多解决方案中的一个


不使用BigInteger的一个原因:

BigInteger x = new BigInteger("00001234", 16);
byte[] input = x.toByteArray();
System.out.println(Arrays.toString(input));

前导零被删除,导致

[18, 52]

BigInteger x = new BigInteger("FFFF", 16);
byte[] input = x.toByteArray();
System.out.println(Arrays.toString(input));

添加了额外的零(使其为正):

[0, -1, -1]


为什么得到错误的结果:

BigInteger x = new BigInteger("f35b", 16);
System.out.println(Integer.toHexString(x.byteValue()));

结果为5b,即给定BigInteger的低字节。