0
votes

I am generating a HMAC, sha256 hash of a json encoded python dict using json. Lets call it hash1. This is my signature which am sending with JWT. Then I would like to verify this signature at another service in Go. I am using the data that i have in a map(same as python dict), json encoding and hashing it(hash2) However, hash1 and hash2 are different. I learned that this is due to python json adding space between elements in dict. Golang json library doesn't add any space. Is there a way I can work around this?

some_data = {'a':1, 'b':2}
json_str1 = json.dumps(some_data, sort_keys=True)
some_data := map[string]int{"a":1, "b":2}
json_str2 = json.Marshal(some_data)

EDIT: As suggested in one of the answers, using separators in json.dumps would solve the problem. Unfortunately, I do not own the python side code, so can't do the changes there.

3

3 Answers

1
votes

Can't say anything about Go, but when i was generating hash in javascript i had the same issue. You need to play around a bit with separators, maybe something like json.dumps(data, separators=(',', ':')).encode('utf-8') will work.

0
votes

json.Marshal does not stringify. It rather return the json encoding in bytes.

If you want the string conversion, you can use the following.

b, _ := json.Marshal(some_data)
json_str2 := str(b)

Since json.dumps add an extra space between the field value, you can use the following to add an extra space to the json stringified

str := string(b)

fmt.Println(str)
c := strings.Join(strings.Split(str, ","), ", ")
fmt.Println(c)

Using this delimiter might fail in case there are strings value with comma ",".

To make sure not to add any space to strings containing comma, one can use marshalIndent

data, err := json.MarshalIndent(some_data, "", "delimiter")
if err != nil {
    panic(err)
}
fmt.Println(string(data))

s := strings.Replace(string(data), "\ndelimiter", " ", -1)
s = strings.Replace(s, "{ ", "{", -1) 
s = strings.Replace(s, "\n}", "}", -1) 

Python output

json_str1 = json.dumps(some_data, sort_keys=True)


{"a": 1, "b": 2}

Go output

{"a": 1, "b": 2}
0
votes

Json library in golang has a MarshalIndent function that solves this issue.