467cf5456dad0150d1b88748e25ec2b0edfa89ec23fe4aac1699aa49b7ca83a885069053e553b9727450b67b8bcf173526ad73a00bcc65e32a6bd9ffffcc75 3.1 KB

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