Recently needed to translate a code snippet of hashing from Java to Nodejs and I can't get the same result as Java. Sample from Java;
SecretKeySpec signingKey = new SecretKeySpec(client_secret.getBytes(UTF_8), HMAC_SHA256_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
mac.init(signingKey);
byte[] rawBodyHash = mac.doFinal(payload.getBytes(UTF_8));
String bodyHash=new String(Base64.encodeBase64(rawBodyHash)).replace("\r\n", "");
in this snippet client_secret
is a string but payload
is a JSON object.
This is my javascript snippet -
if (!_.isString(body)) {
bodyString = JSON.stringify(body);
}
return createHmac("sha256", this.secret)
.update(bodyString, "utf8")
.digest("base64")
.replace("\r\n", "");
I'm getting very different outputs for the hash.
I suspect that the hashing of a byte array of JSON on java's side is very different compared to the hashing of a JSON.stringify-ed JSON on javascript's side. What would be a good translation of java to javascript, to get the same output?
Edit
when client_secret = 'secret', and payload = {"foo": "bar"};
both of this code snippet gives me the same output.
PzqzmGtlarsXrz6xRD7WwI74//n+qDkVkJ0bQhrsib4=
However when another field is added into the payload, payload = {"foo":"bar", "bar":"foo"} , the output would be different.
Java: 3SsGheXe/TUxVxefwiQGFygrXtx/IkqDzXR9/8ZWPNo=
Javascript: H391/AGzJP3P+ID8AOeq2nsRPmivH+Kc+hXxBf+832Q=
Here is the updated Java snippet
import org.json.JSONObject;
...
JSONObject payload = new JSONObject();
payload.put("foo", "bar");
payload.put("bar", "foo");
...
byte[] rawBodyHash = mac.doFinal(payload.toString().getBytes("UTF-8"));
String bodyHash = new String bodyHash=new String(Base64.encodeBase64(rawBodyHash)).replace("\r\n", "");
I have compared the two payload string values in both languages and they are the same. So why are their output values different?
Edit v2
Thanks @Topaco for pointing out that the order of Java JSON requires an explicit order to be set, otherwise the keys will be sorted in ascending order, making the hash different than the JS's output.
Glad to know that the translation of Java to Javascript works fine, thanks!