'use strict';
|
|
var BN = require('bn.js');
|
var utils = require('../utils');
|
var assert = utils.assert;
|
|
function KeyPair(ec, options) {
|
this.ec = ec;
|
this.priv = null;
|
this.pub = null;
|
|
// KeyPair(ec, { priv: ..., pub: ... })
|
if (options.priv)
|
this._importPrivate(options.priv, options.privEnc);
|
if (options.pub)
|
this._importPublic(options.pub, options.pubEnc);
|
}
|
module.exports = KeyPair;
|
|
KeyPair.fromPublic = function fromPublic(ec, pub, enc) {
|
if (pub instanceof KeyPair)
|
return pub;
|
|
return new KeyPair(ec, {
|
pub: pub,
|
pubEnc: enc,
|
});
|
};
|
|
KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) {
|
if (priv instanceof KeyPair)
|
return priv;
|
|
return new KeyPair(ec, {
|
priv: priv,
|
privEnc: enc,
|
});
|
};
|
|
KeyPair.prototype.validate = function validate() {
|
var pub = this.getPublic();
|
|
if (pub.isInfinity())
|
return { result: false, reason: 'Invalid public key' };
|
if (!pub.validate())
|
return { result: false, reason: 'Public key is not a point' };
|
if (!pub.mul(this.ec.curve.n).isInfinity())
|
return { result: false, reason: 'Public key * N != O' };
|
|
return { result: true, reason: null };
|
};
|
|
KeyPair.prototype.getPublic = function getPublic(compact, enc) {
|
// compact is optional argument
|
if (typeof compact === 'string') {
|
enc = compact;
|
compact = null;
|
}
|
|
if (!this.pub)
|
this.pub = this.ec.g.mul(this.priv);
|
|
if (!enc)
|
return this.pub;
|
|
return this.pub.encode(enc, compact);
|
};
|
|
KeyPair.prototype.getPrivate = function getPrivate(enc) {
|
if (enc === 'hex')
|
return this.priv.toString(16, 2);
|
else
|
return this.priv;
|
};
|
|
KeyPair.prototype._importPrivate = function _importPrivate(key, enc) {
|
this.priv = new BN(key, enc || 16);
|
|
// Ensure that the priv won't be bigger than n, otherwise we may fail
|
// in fixed multiplication method
|
this.priv = this.priv.umod(this.ec.curve.n);
|
};
|
|
KeyPair.prototype._importPublic = function _importPublic(key, enc) {
|
if (key.x || key.y) {
|
// Montgomery points only have an `x` coordinate.
|
// Weierstrass/Edwards points on the other hand have both `x` and
|
// `y` coordinates.
|
if (this.ec.curve.type === 'mont') {
|
assert(key.x, 'Need x coordinate');
|
} else if (this.ec.curve.type === 'short' ||
|
this.ec.curve.type === 'edwards') {
|
assert(key.x && key.y, 'Need both x and y coordinate');
|
}
|
this.pub = this.ec.curve.point(key.x, key.y);
|
return;
|
}
|
this.pub = this.ec.curve.decodePoint(key, enc);
|
};
|
|
// ECDH
|
KeyPair.prototype.derive = function derive(pub) {
|
if(!pub.validate()) {
|
assert(pub.validate(), 'public point not validated');
|
}
|
return pub.mul(this.priv).getX();
|
};
|
|
// ECDSA
|
KeyPair.prototype.sign = function sign(msg, enc, options) {
|
return this.ec.sign(msg, this, enc, options);
|
};
|
|
KeyPair.prototype.verify = function verify(msg, signature) {
|
return this.ec.verify(msg, signature, this);
|
};
|
|
KeyPair.prototype.inspect = function inspect() {
|
return '<Key priv: ' + (this.priv && this.priv.toString(16, 2)) +
|
' pub: ' + (this.pub && this.pub.inspect()) + ' >';
|
};
|