Skip to content
Advertisement

How to correctly calculate HMAC in Google Apps Script using hexadecimal key

I am trying to use API which requires HMAC to authenticate. I was able to generate and use correct key using PHP (using instructions from vendor), but now I need to do the same in Google Apps Script, but I failed…

The API key provided by vendor is C77C96EEF6F6995B with information that this is 8 byte hexadecimal.

Below is my working PHP script:

<?php
$klucz = chr(hexdec('C7')).chr(hexdec('7C')).chr(hexdec('96')).chr(hexdec('EE')).chr(hexdec('F6')).chr(hexdec('F6')).chr(hexdec('99')).chr(hexdec('5B'));
$url = "https://www.ifirma.pl/iapi/abonent/miesiacksiegowy.json";
$nazwaUsera = "WIJARAY978@NIEKIE.COM";
$nazwaKlucza = "abonent";
$hashWiadomosci = hash_hmac("sha1",$url.$nazwaUsera.$nazwaKlucza, $klucz);
echo $hashWiadomosci;
?>

It generates a hash: 9b5f9bb41ac30b9c55b10f3cecdd6e12e852f274 which when I’m using it with postman calling the API is working fine. Problem is when I’m trying to replicate that in Google apps script in similar way:

function bytesToHex(data) {
    return data.map(function(e) {
        var v = (e < 0 ? e + 256 : e).toString(16);
        return v.length == 1 ? "0" + v : v;
    }).join("");
}

function callNumbers() {
  var klucz = String.fromCharCode(parseInt("C7",16))+String.fromCharCode(parseInt("7C",16))+String.fromCharCode(parseInt("96",16))+String.fromCharCode(parseInt("EE",16))+String.fromCharCode(parseInt("F6",16))+String.fromCharCode(parseInt("F6",16))+String.fromCharCode(parseInt("99",16))+String.fromCharCode(parseInt("5B",16)); 

  var user = "WIJARAY978@NIEKIE.COM"
  var url = "https://www.ifirma.pl/iapi/abonent/miesiacksiegowy.json";
  var wiadomosc = url+user+"abonent";

  var hmac = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_1, wiadomosc, klucz);
  
  hmac=bytesToHex(hmac)
  Logger.log(hmac);
}

This returns me completely different calculated hash: 6f50edae11b1f7f5b8488a99c4df3e797662c739

Please help me to debug it.

btw. Credentials inside the code are working ones for dummy account.

Advertisement

Answer

In your script, how about converting the HEX values of $klucz = chr(hexdec('C7')).chr(hexdec('7C')).chr(hexdec('96')).chr(hexdec('EE')).chr(hexdec('F6')).chr(hexdec('F6')).chr(hexdec('99')).chr(hexdec('5B')); to the byte array in Google Apps Script? At Google Apps Script, I thought that to use the byte array might be suitable rather than the use of the binary data.

When this is reflected in your script, it becomes as follows.

Modified script:

In this modification, the function callNumbers() is modified.

function callNumbers() {
  var hex = "C77C96EEF6F6995B";
  var klucz = hex.match(/.{2}/g).map(e => parseInt(e[0], 16).toString(2).length == 4 ? parseInt(e, 16) - 256: parseInt(e, 16));

  var user = "WIJARAY978@NIEKIE.COM"
  var url = "https://www.ifirma.pl/iapi/abonent/miesiacksiegowy.json";
  var wiadomosc = url+user+"abonent";

  var hmac = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_1, Utilities.newBlob(wiadomosc).getBytes(), klucz);
  
  hmac=bytesToHex(hmac)
  Logger.log(hmac);
}
  • By converting the HEX value to the byte array, the arguments of Utilities.computeHmacSignature are also required to be converted to the byte array.
  • When this script is run, 9b5f9bb41ac30b9c55b10f3cecdd6e12e852f274 is obtained. This is the same value with the value by your PHP script.
  • Of course, var klucz = ['C7', '7C', '96', 'EE', 'F6', 'F6', '99', '5B'].map(e => parseInt(e[0], 16).toString(2).length == 4 ? parseInt(e, 16) - 256 : parseInt(e, 16)); can be also used.

Reference:

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement