var qs = require('qs'); var crypto = require('crypto'); /** * Verify HMAC * @param proto * @param hostname * @param url * @param method * @param params * @param nonce * @param apikey * @param hmacsig * @returns {boolean} */ function verifyHMAC(proto, hostname, url, method, params, nonce, apikey, hmacsig) { var url = proto + "://" + hostname + url; // Sort the params. var sorted_params = qs.stringify(params, { arrayFormat: 'brackets' }).split("&").sort(sortByPropertyOnly).join("&").replace(/%20/g, '+'); var data = nonce + "|" + method + "|" + url + "|" + sorted_params; var computed_sig = crypto.createHmac('sha256', apikey).update(data).digest('base64'); return hmacsig == computed_sig; } /** * Sort by property only. * Normal JS sort parses the entire string so a stringified array value like 'events=zzzz' * would be moved after 'events=aaaa'. * * Instead we split tokenize the string around the '=' value and only sort alphabetically * by the property. * * @param {string} x * @param {string} y * @returns {number} */ function sortByPropertyOnly(x, y){ var xx = x.split("="); var yy = y.split("="); if (xx < yy) { return -1; } if (xx > yy) { return 1; } return 0; }