生成的 SHA512 字符串与 Java 中生成的字符串不同。

huangapple go评论76阅读模式
英文:

sha512 string generated is different from string generated in java

问题

我正在尝试生成一个类似于Java代码生成的哈希值,以便稍后在数据库中进行重复检查时可以进行比较。

这是Java代码生成哈希值的方式:

public String getHash(String algorithm, String message, String salt) throws NoSuchAlgorithmException {
    // Create MessageDigest instance for given algorithm
    MessageDigest md = MessageDigest.getInstance("SHA-512");
    md.update(salt.getBytes());
    byte[] bytes = md.digest(message.getBytes());

    // Convert it to hexadecimal format
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < bytes.length; i++) {
        sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16)
                .substring(1));
    }
    return sb.toString();
}

这是我用Go语言编写的代码:

func HashSha512(original string) (string, error) {

    salt := "abcde687869"

    originalStrBytes := []byte(original)
    sha512Hasher := sha512.New()
    saltedValueBytes := append(originalStrBytes, []byte(salt)...)
    sha512Hasher.Write(saltedValueBytes)
    hashedBytes := sha512Hasher.Sum(nil)

    s := ""
    var x uint64 = 0x100
    y := byte(x)
    for i := 0; i < len(hashedBytes); i++ {
        s += fmt.Sprintf("%x", ((hashedBytes[i] & 0xff) + y))[1:]
    }

    return s, nil
}

但是生成的字符串不相同。

Go Playground链接:https://play.golang.com/p/uXaw7y2tklN

在Go中生成的字符串是:

99461a225184c478b8398c7f0dcc1d3afed107660d08a7282a10f5e2ab6

而在Java中生成的字符串是:

020e93364e5186b7d4ac211cd116425234937d390fcc4e1c554fa1e4bafcb934493047ab841e06f00aa28aabee43b737a6bae2f3fc52e431dde724e691aa952d

我做错了什么?

英文:

I am trying to generate a hash similar to one generated in java code so that they can be compared to check for duplicates later in database.

This is how the java code generates it:

public String getHash(String algorithm, String message, String salt) throws NoSuchAlgorithmException {
        // Create MessageDigest instance for given algorithm
        MessageDigest md = MessageDigest.getInstance(&quot;SHA-512&quot;);
        md.update(salt.getBytes());
        byte[] bytes = md.digest(message.getBytes());

        // Convert it to hexadecimal format
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i &lt; bytes.length; i++) {
            sb.append(Integer.toString((bytes[i] &amp; 0xff) + 0x100, 16)
                    .substring(1));
        }
        return sb.toString();
    }

This is how I have written in Go:

func HashSha512(original string) (string, error) {

	salt := &quot;abcde687869&quot;

	originalStrBytes := []byte(original)
	sha512Hasher := sha512.New()
	saltedValueBytes := append(originalStrBytes, []byte(salt)...)
	sha512Hasher.Write(saltedValueBytes)
	hashedBytes := sha512Hasher.Sum(nil)

	s := &quot;&quot;
	var x uint64 = 0x100
	y := byte(x)
	for i := 0; i &lt; len(hashedBytes); i++ {
		s += fmt.Sprintf(&quot;%x&quot;, ((hashedBytes[i] &amp; 0xff) + y))[1:]
	}

	return s, nil
}

But the strings generated are not the same.

Go playground link: https://play.golang.com/p/uXaw7y2tklN

String generated is

99461a225184c478b8398c7f0dcc1d3afed107660d08a7282a10f5e2ab6

The string generated for same string in java is

020e93364e5186b7d4ac211cd116425234937d390fcc4e1c554fa1e4bafcb934493047ab841e06f00aa28aabee43b737a6bae2f3fc52e431dde724e691aa952d

What am I doing wrong?

答案1

得分: 2

Go代码对消息+盐进行哈希处理。Java代码对盐+消息进行哈希处理。将Go代码中的顺序调换以匹配Java代码。

在转换为十六进制时,使用整数值而不是字节。当使用字节时,0x100会转换为零:

s += fmt.Sprintf("%x", ((int(hashedBytes[i]) & 0xff) + 0x100))[1:]

更好的做法是使用库函数进行转换。使用encoding/hex:

return hex.EncodeToString(hashedBytes)

使用fmt:

return fmt.Sprintf("%x", hashedBytes)

字符串转换为字节时可能存在差异。Java代码使用平台的默认字符集。假设Go应用程序使用UTF-8编码字符串,这是典型的情况,转换后的字节是UTF-8编码的。

以下是函数的简化版本:

func HashSha512hex(original string) (string, error) {
	salt := "abcde6786"
	h := sha512.New()
	io.WriteString(h, salt)
	io.WriteString(h, original)
	s := h.Sum(nil)
	return hex.EncodeToString(s), nil
}
英文:

The Go code hashes message + salt. The Java code hashes salt + message. Swap the order in the Go code to match the Java code.

Use integer values instead of bytes in the conversion to hex. The 0x100 is converted to zero when using bytes:

s += fmt.Sprintf(&quot;%x&quot;, ((int(hashedBytes[i]) &amp; 0xff) + 0x100))[1:]

Better yet, use a library function for the conversion. Using encoding/hex:

return hex.EncodeToString(hashedBytes)

Using fmt:

return fmt.Sprintf(&quot;%x&quot;, hashedBytes)

There may be a difference in how the strings are encoded to bytes. The Java code uses the platform's default charset. Assuming that the Go application uses UTF-8 encode strings as is typical, the converted bytes are UTF-8 encoded.

Here's a simpler version of the function:

func HashSha512hex(original string) (string, error) {
	salt := &quot;abcde6786&quot;
	h := sha512.New()
	io.WriteString(h, salt)
	io.WriteString(h, original)
	s := h.Sum(nil)
	return hex.EncodeToString(s), nil
}

huangapple
  • 本文由 发表于 2021年11月15日 13:56:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/69969989.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定