Blame view

node_modules/http-signature/lib/verify.js 3.02 KB
f7563de62   Palak Handa   first commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  // Copyright 2015 Joyent, Inc.
  
  var assert = require('assert-plus');
  var crypto = require('crypto');
  var sshpk = require('sshpk');
  var utils = require('./utils');
  
  var HASH_ALGOS = utils.HASH_ALGOS;
  var PK_ALGOS = utils.PK_ALGOS;
  var InvalidAlgorithmError = utils.InvalidAlgorithmError;
  var HttpSignatureError = utils.HttpSignatureError;
  var validateAlgorithm = utils.validateAlgorithm;
  
  ///--- Exported API
  
  module.exports = {
    /**
     * Verify RSA/DSA signature against public key.  You are expected to pass in
     * an object that was returned from `parse()`.
     *
     * @param {Object} parsedSignature the object you got from `parse`.
     * @param {String} pubkey RSA/DSA private key PEM.
     * @return {Boolean} true if valid, false otherwise.
     * @throws {TypeError} if you pass in bad arguments.
     * @throws {InvalidAlgorithmError}
     */
    verifySignature: function verifySignature(parsedSignature, pubkey) {
      assert.object(parsedSignature, 'parsedSignature');
      if (typeof (pubkey) === 'string' || Buffer.isBuffer(pubkey))
        pubkey = sshpk.parseKey(pubkey);
      assert.ok(sshpk.Key.isKey(pubkey, [1, 1]), 'pubkey must be a sshpk.Key');
  
      var alg = validateAlgorithm(parsedSignature.algorithm);
      if (alg[0] === 'hmac' || alg[0] !== pubkey.type)
        return (false);
  
      var v = pubkey.createVerify(alg[1]);
      v.update(parsedSignature.signingString);
      return (v.verify(parsedSignature.params.signature, 'base64'));
    },
  
    /**
     * Verify HMAC against shared secret.  You are expected to pass in an object
     * that was returned from `parse()`.
     *
     * @param {Object} parsedSignature the object you got from `parse`.
     * @param {String} secret HMAC shared secret.
     * @return {Boolean} true if valid, false otherwise.
     * @throws {TypeError} if you pass in bad arguments.
     * @throws {InvalidAlgorithmError}
     */
    verifyHMAC: function verifyHMAC(parsedSignature, secret) {
      assert.object(parsedSignature, 'parsedHMAC');
      assert.string(secret, 'secret');
  
      var alg = validateAlgorithm(parsedSignature.algorithm);
      if (alg[0] !== 'hmac')
        return (false);
  
      var hashAlg = alg[1].toUpperCase();
  
      var hmac = crypto.createHmac(hashAlg, secret);
      hmac.update(parsedSignature.signingString);
  
      /*
       * 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());
      h1 = h1.digest();
      var h2 = crypto.createHmac(hashAlg, secret);
      h2.update(new Buffer(parsedSignature.params.signature, 'base64'));
      h2 = h2.digest();
  
      /* Node 0.8 returns strings from .digest(). */
      if (typeof (h1) === 'string')
        return (h1 === h2);
      /* And node 0.10 lacks the .equals() method on Buffers. */
      if (Buffer.isBuffer(h1) && !h1.equals)
        return (h1.toString('binary') === h2.toString('binary'));
  
      return (h1.equals(h2));
    }
  };