nchaulet / node-geocoder

nodejs geocoding library
http://nchaulet.github.io/node-geocoder/
MIT License
930 stars 214 forks source link

Google Geocoding: pass buffer to crypto.createHmac instead of string #176

Closed ghost closed 8 years ago

ghost commented 8 years ago

Buffer.toString('binary') in Node.js 6 (v6.2.1) results with different string compared to Node.js 4 (v4.2.2).

Example:

const str = '9!H+88WK#1Hf1GR!9acS@E/8d+A1bM';
const hmacBinary = crypto.createHmac('sha1', new Buffer(str, 'base64').toString('binary'));
hmacBinary.update('some data to hash');
// node 4: A+7vPWdMrDCw1M6xvytfodqdwzg=
// node 6: kOGH7NoCHjJafi6rANRTfrH19z0=
console.log(hmacBinary.digest('base64'));

const hmac = crypto.createHmac('sha1', new Buffer(str, 'base64'));
hmac.update('some data to hash');
// node 4: A+7vPWdMrDCw1M6xvytfodqdwzg=
// node 6: A+7vPWdMrDCw1M6xvytfodqdwzg=
console.log(hmac.digest('base64'));

As you can see above, resulting string is different on Node.js 4 and 6, which causes Google API to respond with 403 on Node.js 6, because key is encrypted incorrectly.

If we dive into crypto.createHmac implementation we can see, that key passed buffer is converted to a buffer from a string

function Hmac(hmac, key, options) {
  ...
  this._handle.init(hmac, toBuf(key));
}
function toBuf(str, encoding) {
  if (typeof str === 'string') {
    if (encoding === 'buffer' || !encoding)
      encoding = 'utf8';
    return Buffer.from(str, encoding);
  }
  return str;
}

More details: https://github.com/nodejs/node/blob/master/lib/crypto.js

My suggestion is to omit toString('base64') so that the resulting encoded key will be correct.

nchaulet commented 8 years ago

I will give this a look tonight but looks great 👍

nchaulet commented 8 years ago

Thanks for the fix just published the version v3.12.0

ghost commented 8 years ago

Thank you.