verify.js 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. 'use strict';
  2. // much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
  3. var Buffer = require('safe-buffer').Buffer;
  4. var BN = require('bn.js');
  5. var EC = require('elliptic').ec;
  6. var parseKeys = require('parse-asn1');
  7. var curves = require('./curves.json');
  8. function verify(sig, hash, key, signType, tag) {
  9. var pub = parseKeys(key);
  10. if (pub.type === 'ec') {
  11. // rsa keys can be interpreted as ecdsa ones in openssl
  12. if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') { throw new Error('wrong public key type'); }
  13. return ecVerify(sig, hash, pub);
  14. } else if (pub.type === 'dsa') {
  15. if (signType !== 'dsa') { throw new Error('wrong public key type'); }
  16. return dsaVerify(sig, hash, pub);
  17. }
  18. if (signType !== 'rsa' && signType !== 'ecdsa/rsa') { throw new Error('wrong public key type'); }
  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 += 1;
  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) >= 0) { throw new Error('invalid sig'); }
  74. }
  75. module.exports = verify;