Converting HMAC-SHA1 from node.js to Java

僤鯓⒐⒋嵵緔 提交于 2019-12-10 00:20:29

问题


I have been tasked with converting some existing piece of node.js code to Java. I think I'm well on my way, but I'm kind of stuck right now. The output of the methods do not seem to match.

What I'm doing is creating a SHA-1 signature based on a query string. This query string contains some query-related data (not relevant for this question) and an API key.

Important

  • The api_secret string in node.js is equivalent to Config.API_SECRET in Java.
  • Example query string (these are equal in the node.js and Java program):
    /events?festival=imaginate&pretty=1&size=100&from=0&key=SOME_KEY

Actual code

The SHA-1 hmac is initialized as follows in nodejs:

const hmac = crypto.createHmac('sha1', api_secret);

The SHA-1 mac is initialized as follows in Java:

final SecretKeySpec secretKeySpec = new SecretKeySpec(Config.API_SECRET.getBytes("UTF-8"), "HmacSHA1");
final Mac hmac = Mac.getInstance("HmacSHA1");
hmac.init(secretKeySpec);

Next, the node.js program updates the hmac as such (query parameter is as listed above):

hmac.update(query, 'ascii');

Which I replicated in Java like this (query parameter is equal to the node.js query parameter):

hmac.update(query.getBytes("US-ASCII"));

Finally, the byte string is converted to a SHA-1 hash as such in the node.js program:

const signature = hmac.digest('hex');

I couldn't find an exact translation to Java, but this was my attempt, which I think does about the same thing:

Byte array to hex function

public static String byteArrayToHex(byte[] a) {
    StringBuilder sb = new StringBuilder(a.length * 2);
    for(byte b: a)
        sb.append(String.format("%02x", b & 0xff));
    return sb.toString();
}

Actual usage

byte[] result = hmac.doFinal();
MessageDigest md = MessageDigest.getInstance("SHA-1");
String sha1Hash = byteArrayToHex(md.digest(result));

However, this is where I get confused. The node.js program returns this hash: 18cf4fce7bd6163c64d3b2ea8d935b0f16720fe3

But my Java program gives this hash as output: f65f8738cce89134dc73709e3353d94c83ccf1fb

I can't figure out where I went wrong and I really hope someone could shed a light on this.


回答1:


I figured it out!

Turns out I was doing one unnecessary step.

This line:

byte[] result = mac.doFinal();

Already contained the signature hash. I needed to convert that byte array to a hex string, not the digest of that byte array.

So the working code was simply:

byte[] result = mac.doFinal();
return byteArrayToHex(result);


来源:https://stackoverflow.com/questions/39749956/converting-hmac-sha1-from-node-js-to-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!