I am trying to implement an HMAC signature in node from the vendor’s provided Java example (their documentation was quite lacking, not detailing encodings, or requirements).
The vendor’s provided Java code:
// encrypt strToSign by SHA algorithm
var signingKey = new SecretKeySpec(clientSecret.getBytes(), "HmacSHA256");
var mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
signedStr = bytesToHexString(mac.doFinal(strToSign.getBytes()));
function bytesToHexString(bytes) {
if (bytes == null) {
return null;
}
sb = "";
for (var b of bytes) {
var hv = String.format("%02x", b);
sb += hv;
}
return sb.toLowerCase();
}
My JavaScript code:
var signedStr = crypto
.createHmac('SHA256', Buffer.from(clientSecret, "utf8"))
.update(strToSign, "utf8")
.digest('hex');
Getting a an error: msg: 'Signature does not match'
result from the server. I have tried almost every combination I can think of changing the encoding of the client secret and strToSign
.
I usually can figure out how to get my problems fixed with a quick search. And I feel extremely close. However now I am at a nexus wherein I cannot quite determine what nuances between the provided Java code and my attempt at a Node translation. I feel that it is going to be related to encoding, off by one, or big endian type issue. Unfortunately with hash/signatures I cannot just brute force my way to an answer (I have tried).
2
Answers
If you inputs are already strings, you can encode them directly.
Both calls log
7c13c6e89d4402cf331c7b0cb6a16b98f04144a247f796e6afaaae1cff64af0d
The issue you’re facing is likely related to how you’re handling the encoding of the
strToSign
andclientSecret
in your JavaScript code compared to the Java code provided by the vendor. HMAC signatures are sensitive to the input encoding, so it’s crucial to ensure that both the key and the data being hashed are encoded in the same way. Here’s how you can translate the Java HMAC code to Node.js:In this code:
We use
Buffer.from
to convert theclientSecret
andstrToSign
strings into UTF-8 encoded buffers. This ensures that the encoding matches the Java code.We create an HMAC instance using SHA-256 and initialize it with the
clientSecret
buffer as the key.We update the HMAC instance with the
dataBuffer
, which contains the string you want to sign.Finally, we obtain the hexadecimal representation of the HMAC signature using
.digest('hex')
.Ensure that you are using the correct
clientSecret
andstrToSign
values, and that they match the Java code. This should resolve the issue of the signature not matching on the server side.