| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 | // much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.jsvar Buffer = require('safe-buffer').Buffervar BN = require('bn.js')var EC = require('elliptic').ecvar 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 = Buffer.from(pad)  var red = BN.mont(pub.modulus)  sig = new BN(sig).toRed(red)  sig = sig.redPow(new BN(pub.publicExponent))  sig = Buffer.from(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
 |