Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go SHA-256 hash differs from Java SHA-256 hash

Tags:

java

hash

go

sha

If I generate the SHA-256 hash in the language "GO", I get a different byte-Array compared to the Java equivalent.

This is the GO version:

fmt.Println(getSha256([]byte("5nonce=5")))

The resulting array looks like:

41 79 186 235 199 123 95 226 16 59 51 161 112 245 192 50 21 66 180 250 179 109 153 18 233 148 16 237 156 69 163 150]

This one should do the same in Java code:

MessageDigest md = MessageDigest.getInstance("SHA-256");

md.update("5nonce=5".getBytes()); 
byte[] digest = md.digest();

But results in this byte array

[41, 79, -70, -21, -57, 123, 95, -30, 16, 59, 51, -95, 112, -11, -64, 50, 21, 66, -76, -6, -77, 109, -103, 18, -23, -108, 16, -19, -100, 69, -93, -106]

Why are they different? How do I need to change the java version to work exactly like the Go version?

like image 344
jan Avatar asked Jun 27 '14 22:06

jan


2 Answers

Why are they different?

They're not, really. They're the same bits. It's just that Java doesn't have unsigned bytes - so any byte with the top bit set is negative. In every case like that, you'll see that Java result = Go result - 256.

If you convert both byte arrays to hex or base64, you'll see same results.

like image 191
Jon Skeet Avatar answered Sep 20 '22 07:09

Jon Skeet


Here is the Go code which would produce the same result:

package main

import "fmt"
import "crypto/sha256"

func main() {
    sum224 := sha256.Sum256([]byte("5nonce=5"))
    s := make([]int8, sha256.Size)
    for i := range sum224 {
        s[i] = int8(sum224[i])
    }
    fmt.Printf("%d", s)
}

[41 79 -70 -21 -57 123 95 -30 16 59 51 -95 112 -11 -64 50 21 66 -76 -6 -77 109 -103 18 -23 -108 16 -19 -100 69 -93 -106]

The fmt doc does mention:

There is no 'u' flag. Integers are printed unsigned if they have unsigned type.

Since Numeric Types defines:

  • byte alias for uint8
  • uint8 the set of all unsigned 8-bit integers (0 to 255)
  • int8 the set of all signed 8-bit integers (-128 to 127)

That is why you would need to convert byte (unsigned) into signed int8 to see the same.


If you add base64 encoding (see golang playground), you can get a result easier to compare:

import "encoding/base64"

res := base64.StdEncoding.EncodeToString([]byte(sum224[:]))
fmt.Println(res)

That returns:

KU+668d7X+IQOzOhcPXAMhVCtPqzbZkS6ZQQ7ZxFo5Y=
like image 35
VonC Avatar answered Sep 21 '22 07:09

VonC