Blame view

node_modules/browserify-sign/browser/verify.js 2.33 KB
aaac7fed   liuqimichale   add
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
  // much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
  var BN = require('bn.js')
  var EC = require('elliptic').ec
  var parseKeys = require('parse-asn1')
  var curves = require('./curves.json')
  
  function verify (sig, hash, key, signType, tag) {
    var pub = parseKeys(key)
    if (pub.type === 'ec') {
      // rsa keys can be interpreted as ecdsa ones in openssl
      if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type')
      return ecVerify(sig, hash, pub)
    } else if (pub.type === 'dsa') {
      if (signType !== 'dsa') throw new Error('wrong public key type')
      return dsaVerify(sig, hash, pub)
    } else {
      if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type')
    }
    hash = Buffer.concat([tag, hash])
    var len = pub.modulus.byteLength()
    var pad = [ 1 ]
    var padNum = 0
    while (hash.length + pad.length + 2 < len) {
      pad.push(0xff)
      padNum++
    }
    pad.push(0x00)
    var i = -1
    while (++i < hash.length) {
      pad.push(hash[i])
    }
    pad = new Buffer(pad)
    var red = BN.mont(pub.modulus)
    sig = new BN(sig).toRed(red)
  
    sig = sig.redPow(new BN(pub.publicExponent))
    sig = new Buffer(sig.fromRed().toArray())
    var out = padNum < 8 ? 1 : 0
    len = Math.min(sig.length, pad.length)
    if (sig.length !== pad.length) out = 1
  
    i = -1
    while (++i < len) out |= sig[i] ^ pad[i]
    return out === 0
  }
  
  function ecVerify (sig, hash, pub) {
    var curveId = curves[pub.data.algorithm.curve.join('.')]
    if (!curveId) throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.'))
  
    var curve = new EC(curveId)
    var pubkey = pub.data.subjectPrivateKey.data
  
    return curve.verify(hash, sig, pubkey)
  }
  
  function dsaVerify (sig, hash, pub) {
    var p = pub.data.p
    var q = pub.data.q
    var g = pub.data.g
    var y = pub.data.pub_key
    var unpacked = parseKeys.signature.decode(sig, 'der')
    var s = unpacked.s
    var r = unpacked.r
    checkValue(s, q)
    checkValue(r, q)
    var montp = BN.mont(p)
    var w = s.invm(q)
    var v = g.toRed(montp)
      .redPow(new BN(hash).mul(w).mod(q))
      .fromRed()
      .mul(y.toRed(montp).redPow(r.mul(w).mod(q)).fromRed())
      .mod(p)
      .mod(q)
    return v.cmp(r) === 0
  }
  
  function checkValue (b, q) {
    if (b.cmpn(0) <= 0) throw new Error('invalid sig')
    if (b.cmp(q) >= q) throw new Error('invalid sig')
  }
  
  module.exports = verify