key.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. 'use strict';
  2. var BN = require('bn.js');
  3. var elliptic = require('../../elliptic');
  4. var utils = elliptic.utils;
  5. var assert = utils.assert;
  6. function KeyPair(ec, options) {
  7. this.ec = ec;
  8. this.priv = null;
  9. this.pub = null;
  10. // KeyPair(ec, { priv: ..., pub: ... })
  11. if (options.priv)
  12. this._importPrivate(options.priv, options.privEnc);
  13. if (options.pub)
  14. this._importPublic(options.pub, options.pubEnc);
  15. }
  16. module.exports = KeyPair;
  17. KeyPair.fromPublic = function fromPublic(ec, pub, enc) {
  18. if (pub instanceof KeyPair)
  19. return pub;
  20. return new KeyPair(ec, {
  21. pub: pub,
  22. pubEnc: enc
  23. });
  24. };
  25. KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) {
  26. if (priv instanceof KeyPair)
  27. return priv;
  28. return new KeyPair(ec, {
  29. priv: priv,
  30. privEnc: enc
  31. });
  32. };
  33. KeyPair.prototype.validate = function validate() {
  34. var pub = this.getPublic();
  35. if (pub.isInfinity())
  36. return { result: false, reason: 'Invalid public key' };
  37. if (!pub.validate())
  38. return { result: false, reason: 'Public key is not a point' };
  39. if (!pub.mul(this.ec.curve.n).isInfinity())
  40. return { result: false, reason: 'Public key * N != O' };
  41. return { result: true, reason: null };
  42. };
  43. KeyPair.prototype.getPublic = function getPublic(compact, enc) {
  44. // compact is optional argument
  45. if (typeof compact === 'string') {
  46. enc = compact;
  47. compact = null;
  48. }
  49. if (!this.pub)
  50. this.pub = this.ec.g.mul(this.priv);
  51. if (!enc)
  52. return this.pub;
  53. return this.pub.encode(enc, compact);
  54. };
  55. KeyPair.prototype.getPrivate = function getPrivate(enc) {
  56. if (enc === 'hex')
  57. return this.priv.toString(16, 2);
  58. else
  59. return this.priv;
  60. };
  61. KeyPair.prototype._importPrivate = function _importPrivate(key, enc) {
  62. this.priv = new BN(key, enc || 16);
  63. // Ensure that the priv won't be bigger than n, otherwise we may fail
  64. // in fixed multiplication method
  65. this.priv = this.priv.umod(this.ec.curve.n);
  66. };
  67. KeyPair.prototype._importPublic = function _importPublic(key, enc) {
  68. if (key.x || key.y) {
  69. // Montgomery points only have an `x` coordinate.
  70. // Weierstrass/Edwards points on the other hand have both `x` and
  71. // `y` coordinates.
  72. if (this.ec.curve.type === 'mont') {
  73. assert(key.x, 'Need x coordinate');
  74. } else if (this.ec.curve.type === 'short' ||
  75. this.ec.curve.type === 'edwards') {
  76. assert(key.x && key.y, 'Need both x and y coordinate');
  77. }
  78. this.pub = this.ec.curve.point(key.x, key.y);
  79. return;
  80. }
  81. this.pub = this.ec.curve.decodePoint(key, enc);
  82. };
  83. // ECDH
  84. KeyPair.prototype.derive = function derive(pub) {
  85. return pub.mul(this.priv).getX();
  86. };
  87. // ECDSA
  88. KeyPair.prototype.sign = function sign(msg, enc, options) {
  89. return this.ec.sign(msg, this, enc, options);
  90. };
  91. KeyPair.prototype.verify = function verify(msg, signature) {
  92. return this.ec.verify(msg, signature, this);
  93. };
  94. KeyPair.prototype.inspect = function inspect() {
  95. return '<Key priv: ' + (this.priv && this.priv.toString(16, 2)) +
  96. ' pub: ' + (this.pub && this.pub.inspect()) + ' >';
  97. };