微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决在java中使用SHA-256散列一个十六进制数

我编写了一个代码来使用 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的低字节。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。