Projekt

Obecné

Profil

Stáhnout (2.33 KB) Statistiky
| Větev: | Revize:
1 3a515b92 cagy
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
2
var BN = require('bn.js')
3
var EC = require('elliptic').ec
4
var parseKeys = require('parse-asn1')
5
var curves = require('./curves.json')
6
7
function verify (sig, hash, key, signType, tag) {
8
  var pub = parseKeys(key)
9
  if (pub.type === 'ec') {
10
    // rsa keys can be interpreted as ecdsa ones in openssl
11
    if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type')
12
    return ecVerify(sig, hash, pub)
13
  } else if (pub.type === 'dsa') {
14
    if (signType !== 'dsa') throw new Error('wrong public key type')
15
    return dsaVerify(sig, hash, pub)
16
  } else {
17
    if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type')
18
  }
19
  hash = Buffer.concat([tag, hash])
20
  var len = pub.modulus.byteLength()
21
  var pad = [ 1 ]
22
  var padNum = 0
23
  while (hash.length + pad.length + 2 < len) {
24
    pad.push(0xff)
25
    padNum++
26
  }
27
  pad.push(0x00)
28
  var i = -1
29
  while (++i < hash.length) {
30
    pad.push(hash[i])
31
  }
32
  pad = new Buffer(pad)
33
  var red = BN.mont(pub.modulus)
34
  sig = new BN(sig).toRed(red)
35
36
  sig = sig.redPow(new BN(pub.publicExponent))
37
  sig = new Buffer(sig.fromRed().toArray())
38
  var out = padNum < 8 ? 1 : 0
39
  len = Math.min(sig.length, pad.length)
40
  if (sig.length !== pad.length) out = 1
41
42
  i = -1
43
  while (++i < len) out |= sig[i] ^ pad[i]
44
  return out === 0
45
}
46
47
function ecVerify (sig, hash, pub) {
48
  var curveId = curves[pub.data.algorithm.curve.join('.')]
49
  if (!curveId) throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.'))
50
51
  var curve = new EC(curveId)
52
  var pubkey = pub.data.subjectPrivateKey.data
53
54
  return curve.verify(hash, sig, pubkey)
55
}
56
57
function dsaVerify (sig, hash, pub) {
58
  var p = pub.data.p
59
  var q = pub.data.q
60
  var g = pub.data.g
61
  var y = pub.data.pub_key
62
  var unpacked = parseKeys.signature.decode(sig, 'der')
63
  var s = unpacked.s
64
  var r = unpacked.r
65
  checkValue(s, q)
66
  checkValue(r, q)
67
  var montp = BN.mont(p)
68
  var w = s.invm(q)
69
  var v = g.toRed(montp)
70
    .redPow(new BN(hash).mul(w).mod(q))
71
    .fromRed()
72
    .mul(y.toRed(montp).redPow(r.mul(w).mod(q)).fromRed())
73
    .mod(p)
74
    .mod(q)
75
  return v.cmp(r) === 0
76
}
77
78
function checkValue (b, q) {
79
  if (b.cmpn(0) <= 0) throw new Error('invalid sig')
80
  if (b.cmp(q) >= q) throw new Error('invalid sig')
81
}
82
83
module.exports = verify