diff --git a/lib/verify.js b/lib/verify.js index f6ad0c2..8c34aee 100644 --- a/lib/verify.js +++ b/lib/verify.js @@ -48,9 +48,23 @@ module.exports = { if (!alg || alg.length !== 2) throw new TypeError('parsedSignature: unsupported algorithm ' + parsedSignature.algorithm); + var hashAlg = alg[1].toUpperCase(); - var hmac = crypto.createHmac(alg[1].toUpperCase(), secret); + var hmac = crypto.createHmac(hashAlg, secret); hmac.update(parsedSignature.signingString); - return (hmac.digest('base64') === parsedSignature.params.signature); + + /* + * Now double-hash to avoid leaking timing information - there's + * no easy constant-time compare in JS, so we use this approach + * instead. See for more info: + * https://www.isecpartners.com/blog/2011/february/double-hmac- + * verification.aspx + */ + var h1 = crypto.createHmac(hashAlg, secret); + h1.update(hmac.digest()); + var h2 = crypto.createHmac(hashAlg, secret); + h2.update(new Buffer(parsedSignature.params.signature, 'base64')); + + return (h1.digest().equals(h2.digest())); } };