gpt4 book ai didi

java - 像 HashCalc 一样获取 HexString 的 SHA1

转载 作者:行者123 更新时间:2023-11-29 07:59:00 26 4
gpt4 key购买 nike

HashCalc在顶部有一个名为“数据格式”的字段,我将其切换为“HexString”,然后在数据字段中输入 9a 的测试值。我对其运行 SHA-1 哈希,答案是:13cba177bcfad90e7b3de70616b2e54ba4bb107f

(注意:在线哈希器会将“9a”作为字符串进行哈希处理,得到的答案为 e8eef065fb7295044d65b305bab18a9a645d1abf。这对这个应用程序来说是错误的)

现在,我需要将这种类型的哈希嵌入到我的 Java 程序中。这是我到目前为止得到的(包含在 try/catch 中):

String ss = "9a";
ByteBuffer bb = ByteBuffer.allocate(8);
byte[] ba = bb.putLong(Long.decode("0x"+ss).longValue()).array();
MessageDigest md = MessageDigest.getInstance("SHA-1");
String results = encodeHex(md.digest(ba));
System.out.println("sha:"+results);

但是,我的结果是 E73C417858807239DD5BC30BA978C14D57F80834

我做错了什么?

编辑:添加了十六进制标签,很明显数据必须是某种十六进制格式。由于 HashCalc 必须设置为“HexString”而不是“TextString”,后者会返回不同的结果。解决方案很可能包括改变我处理这些十六进制数字的方式。 --> 结果是真的

最佳答案

免责声明

OP (Pimp Trizkit) 是找到 the right solution 的人 。我只是使用他的解决方案(稍作改动)来展示结果并获得乐趣。保留所有权利)

此外,OP 提供的字节数组到十六进制字符串转换算法比我的示例代码中的算法快得多。参见 his solution用于实现。
(有关详细信息,请阅读下面的评论)


手动解决方案之一:
(重要!这是我的第一个答案,但它只是为了从文本字符串中获取哈希值,而不是像 OP 要求的那样从十六进制字符串中获取哈希值. 请参阅下面的更新):

import java.security.MessageDigest;

public class TestHash {

public static void main(String[] args) throws Exception {
String password = "9a";

MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(password.getBytes());
byte[] byteData = md.digest();
// byte[] byteData = md.digest(password.getBytes()); // both updates and completes the hash computation

// Method 1 of converting bytes to hex format
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xFF) + 0x100, 16).substring(1));
}

System.out.println("1) Hex format : " + sb.toString());

// Method 2 of converting bytes to hex format
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
String hex = Integer.toHexString(0xff & byteData[i]);
// NB! E.g.: Integer.toHexString(0x0C) will return "C", not "0C"
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
System.out.println("2) Hex format : " + hexString.toString());
}
}

输出:

1) Hex format : e8eef065fb7295044d65b305bab18a9a645d1abf
2) Hex format : e8eef065fb7295044d65b305bab18a9a645d1abf

更新

基于OP found solution ,这里是代码,展示了从 hex string 而不是 text string 获取 SHA-1 哈希。此外,它还提供了几种手动将字节数组转换为十六进制字符串的方法(仅供娱乐)。对不起,我心情不好))

查看我的评论 main方法和里面不同bytesToHexString()重要时刻的解释方法。

import java.security.MessageDigest;
import java.math.BigInteger;
import javax.xml.bind.DatatypeConverter;

public class TestHash3 {

public static void main(String[] args) throws Exception {
String hexString = "1234";

/*
* NB!
* Before passing hex string to DatatypeConverter.parseHexBinary(),
* we need to check if the hex sting is even-length,
* otherwise DatatypeConverter.parseHexBinary() will throw a
* java.lang.IllegalArgumentException: hexBinary needs to be even-length
*/
hexString = (hexString.length() % 2 == 0) ? hexString : "0" + hexString;
byte[] bytes = DatatypeConverter.parseHexBinary(hexString);

MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] byteData = md.digest(bytes);

System.out.println("1) SHA-1 hash for the hex string " + hexString + ": " +
bytesToHexString1(byteData));
System.out.println("2) SHA-1 hash for the hex string " + hexString + ": " +
bytesToHexString2(byteData));
System.out.println("3) SHA-1 hash for the hex string " + hexString + ": " +
bytesToHexString3(byteData));
System.out.println("4) SHA-1 hash for the hex string " + hexString + ": " +
bytesToHexString4(byteData));
}

public static String bytesToHexString1(byte[] bytes) {
StringBuffer hexBuffer = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
hexBuffer.append(Integer.toString((bytes[i] & 0xFF) + 0x100, 16).substring(1));
}

return hexBuffer.toString();
}

public static String bytesToHexString2(byte[] bytes) {
StringBuffer hexBuffer = new StringBuffer(bytes.length * 2);
for (byte b: bytes) {
int n = b & 0xFF; // casting to integer to avoid problems with negative bytes
if (n < 0x10) {
hexBuffer.append("0");
}
hexBuffer.append(Integer.toHexString(n));
}

return hexBuffer.toString();
}

public static String bytesToHexString3(byte[] bytes) {
StringBuffer hexBuffer = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
String hexString = Integer.toHexString(0xff & bytes[i]);
// NB! E.g.: Integer.toHexString(0x0C) will return "C", not "0C"
if (hexString.length() == 1) {
hexBuffer.append('0');
}
hexBuffer.append(hexString);
}

return hexBuffer.toString();
}

public static String bytesToHexString4(byte[] bytes) {
String hexString = new BigInteger(1, bytes).toString(16);

/*
* NB!
* We need an even-length hex string to propely represent bytes in hexadecimal.
* A hexadecimal representation of one byte consists of two hex digits.
* If the value is less than 16 (dec), it is prepended with zero
* E.g.:
* 1 (byte) ==> 01 (hex) // pay attention to the prepended zero
* 15 (byte) ==> 0F (hex)
* 16 (byte) ==> 10 (hex) // no need to prepend
* 255(byte) ==> FF (hex)
*
* BigInteger.toString(16) can return both even and odd-length hex strings.
* E.g.:
* byte[] bytes = {15, 16} // two bytes
* BigInteger(1, bytes).toString(16) will produce (NB!): f10
* But we need (NB!): 0f10
* So we must check if the resulting hex string is even-length,
* and if not, prepend it with zero.
*/
return ((hexString.length() % 2 == 0) ? hexString : "0" + hexString);
}
}

输出:

1) SHA-1 hash for the hex string 1234: ffa76d854a2969e7b9d83868d455512fce0fd74d
2) SHA-1 hash for the hex string 1234: ffa76d854a2969e7b9d83868d455512fce0fd74d
3) SHA-1 hash for the hex string 1234: ffa76d854a2969e7b9d83868d455512fce0fd74d
4) SHA-1 hash for the hex string 1234: ffa76d854a2969e7b9d83868d455512fce0fd74d


顺便说一句,检查十六进制字符串在 byteToHexString4() 中是否为偶数长度所以它可以独立使用。


更新 2

用户@kan带来了另一种将字节数组转换为十六进制字符串的方法,非常简单的一行代码,并且是仅次于 OP 方法的第二快

DatatypeConverter.printHexBinary(byte[] val)

关于java - 像 HashCalc 一样获取 HexString 的 SHA1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15669550/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com