verify.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
  2. var Buffer = require('safe-buffer').Buffer
  3. var BN = require('bn.js')
  4. var EC = require('elliptic').ec
  5. var parseKeys = require('parse-asn1')
  6. var curves = require('./curves.json')
  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 = Buffer.from(pad)
  33. var red = BN.mont(pub.modulus)
  34. sig = new BN(sig).toRed(red)
  35. sig = sig.redPow(new BN(pub.publicExponent))
  36. sig = Buffer.from(sig.fromRed().toArray())
  37. var out = padNum < 8 ? 1 : 0
  38. len = Math.min(sig.length, pad.length)
  39. if (sig.length !== pad.length) out = 1
  40. i = -1
  41. while (++i < len) out |= sig[i] ^ pad[i]
  42. return out === 0
  43. }
  44. function ecVerify (sig, hash, pub) {
  45. var curveId = curves[pub.data.algorithm.curve.join('.')]
  46. if (!curveId) throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.'))
  47. var curve = new EC(curveId)
  48. var pubkey = pub.data.subjectPrivateKey.data
  49. return curve.verify(hash, sig, pubkey)
  50. }
  51. function dsaVerify (sig, hash, pub) {
  52. var p = pub.data.p
  53. var q = pub.data.q
  54. var g = pub.data.g
  55. var y = pub.data.pub_key
  56. var unpacked = parseKeys.signature.decode(sig, 'der')
  57. var s = unpacked.s
  58. var r = unpacked.r
  59. checkValue(s, q)
  60. checkValue(r, q)
  61. var montp = BN.mont(p)
  62. var w = s.invm(q)
  63. var v = g.toRed(montp)
  64. .redPow(new BN(hash).mul(w).mod(q))
  65. .fromRed()
  66. .mul(y.toRed(montp).redPow(r.mul(w).mod(q)).fromRed())
  67. .mod(p)
  68. .mod(q)
  69. return v.cmp(r) === 0
  70. }
  71. function checkValue (b, q) {
  72. if (b.cmpn(0) <= 0) throw new Error('invalid sig')
  73. if (b.cmp(q) >= q) throw new Error('invalid sig')
  74. }
  75. module.exports = verify