diff --git a/lib/elliptic/curve/edwards.js b/lib/elliptic/curve/edwards.js index 85905b3..9c49fd8 100644 --- a/lib/elliptic/curve/edwards.js +++ b/lib/elliptic/curve/edwards.js @@ -13,7 +13,7 @@ function EdwardsCurve(conf) { this.mOneA = this.twisted && conf.a == -1; this.extended = this.mOneA; - Base.call(this, 'mont', conf); + Base.call(this, 'edwards', conf); this.a = new bn(conf.a, 16).mod(this.red.m).toRed(this.red); this.c = new bn(conf.c, 16).toRed(this.red); diff --git a/lib/elliptic/curve/mont.js b/lib/elliptic/curve/mont.js index 903d271..bb40f2a 100644 --- a/lib/elliptic/curve/mont.js +++ b/lib/elliptic/curve/mont.js @@ -25,7 +25,7 @@ MontCurve.prototype.point = function point(x, z) { MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { return Point.fromJSON(this, obj); -} +}; MontCurve.prototype.validate = function validate(point) { var x = point.normalize().x; diff --git a/lib/elliptic/ec/index.js b/lib/elliptic/ec/index.js index a70f571..96764f1 100644 --- a/lib/elliptic/ec/index.js +++ b/lib/elliptic/ec/index.js @@ -35,8 +35,16 @@ function EC(options) { } module.exports = EC; -EC.prototype.keyPair = function keyPair(priv, pub) { - return new KeyPair(this, priv, pub); +EC.prototype.keyPair = function keyPair(options) { + return new KeyPair(this, options); +}; + +EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { + return KeyPair.fromPrivate(this, priv, enc); +}; + +EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { + return KeyPair.fromPublic(this, pub, enc); }; EC.prototype.genKeyPair = function genKeyPair(options) { @@ -59,7 +67,7 @@ EC.prototype.genKeyPair = function genKeyPair(options) { continue; priv.iaddn(1); - return this.keyPair(priv); + return this.keyFromPrivate(priv); } while (true); }; @@ -73,12 +81,17 @@ EC.prototype._truncateToN = function truncateToN(msg, truncOnly) { return msg; }; -EC.prototype.sign = function sign(msg, key, options) { - key = this.keyPair(key, 'hex'); - msg = this._truncateToN(new bn(msg, 16)); +EC.prototype.sign = function sign(msg, key, enc, options) { + if (typeof enc === 'object') { + options = enc; + enc = null; + } if (!options) options = {}; + key = this.keyFromPrivate(key, enc); + msg = this._truncateToN(new bn(msg, 16)); + // Zero-extend key to provide enough entropy var bytes = this.n.byteLength(); var bkey = key.getPrivate().toArray(); @@ -125,9 +138,9 @@ EC.prototype.sign = function sign(msg, key, options) { } while (true); }; -EC.prototype.verify = function verify(msg, signature, key) { +EC.prototype.verify = function verify(msg, signature, key, enc) { msg = this._truncateToN(new bn(msg, 16)); - key = this.keyPair(key, 'hex'); + key = this.keyFromPublic(key, enc); signature = new Signature(signature, 'hex'); // Perform primitive values validation diff --git a/lib/elliptic/ec/key.js b/lib/elliptic/ec/key.js index 396a73a..f71cf06 100644 --- a/lib/elliptic/ec/key.js +++ b/lib/elliptic/ec/key.js @@ -4,47 +4,39 @@ var elliptic = require('../../elliptic'); var utils = elliptic.utils; var assert = utils.assert; -function KeyPair(ec, priv, pub) { - if (priv instanceof KeyPair) - return priv; - if (pub instanceof KeyPair) - return pub; - - if (!priv) { - priv = pub; - pub = null; - } - if (priv !== null && typeof priv === 'object') { - if (priv.x) { - // KeyPair(public) - pub = priv; - priv = null; - } else if (priv.priv || priv.pub) { - // KeyPair({ priv: ..., pub: ... }) - pub = priv.pub; - priv = priv.priv; - } - } - +function KeyPair(ec, options) { this.ec = ec; this.priv = null; this.pub = null; - // KeyPair(public, 'hex') - if (this._importPublicHex(priv, pub)) - return; - - if (pub === 'hex') - pub = null; - - // KeyPair(priv, pub) - if (priv) - this._importPrivate(priv); - if (pub) - this._importPublic(pub); + // 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(); @@ -77,14 +69,19 @@ KeyPair.prototype.getPublic = function getPublic(compact, enc) { for (var i = x.length; i < len; i++) x.unshift(0); - if (compact) { - var res = [ this.pub.getY().isEven() ? 0x02 : 0x03 ].concat(x); + if (this.ec.curve.type !== 'mont') { + if (compact) { + var res = [ this.pub.getY().isEven() ? 0x02 : 0x03 ].concat(x); + } else { + var y = this.pub.getY().toArray(); + for (var i = y.length; i < len; i++) + y.unshift(0); + var res = [ 0x04 ].concat(x, y); + } } else { - var y = this.pub.getY().toArray(); - for (var i = y.length; i < len; i++) - y.unshift(0); - var res = [ 0x04 ].concat(x, y); + res = x; } + return utils.encode(res, enc); }; @@ -95,7 +92,7 @@ KeyPair.prototype.getPrivate = function getPrivate(enc) { return this.priv; }; -KeyPair.prototype._importPrivate = function _importPrivate(key) { +KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { this.priv = new bn(key, 16); // Ensure that the priv won't be bigger than n, otherwise we may fail @@ -103,12 +100,20 @@ KeyPair.prototype._importPrivate = function _importPrivate(key) { this.priv = this.priv.mod(this.ec.curve.n); }; -KeyPair.prototype._importPublic = function _importPublic(key) { - this.pub = this.ec.curve.point(key.x, key.y); -}; +KeyPair.prototype._importPublic = function _importPublic(key, enc) { + if (key.x || key.y) { + this.pub = this.ec.curve.point(key.x, key.y); + return; + } -KeyPair.prototype._importPublicHex = function _importPublic(key, enc) { key = utils.toArray(key, enc); + if (this.ec.curve.type !== 'mont') + return this._importPublicShort(key); + else + return this._importPublicMont(key); +}; + +KeyPair.prototype._importPublicShort = function _importPublicShort(key) { var len = this.ec.curve.p.byteLength(); if (key[0] === 0x04 && key.length - 1 === 2 * len) { this.pub = this.ec.curve.point( @@ -117,11 +122,11 @@ KeyPair.prototype._importPublicHex = function _importPublic(key, enc) { } else if ((key[0] === 0x02 || key[0] === 0x03) && key.length - 1 === len) { this.pub = this.ec.curve.pointFromX(key[0] === 0x03, key.slice(1, 1 +len)); - } else { - return false; } +}; - return true; +KeyPair.prototype._importPublicMont = function _importPublicMont(key) { + this.pub = this.ec.curve.point(key, 1); }; // ECDH diff --git a/test/ecdh-test.js b/test/ecdh-test.js index 13d1a9a..9f8f6f0 100644 --- a/test/ecdh-test.js +++ b/test/ecdh-test.js @@ -12,6 +12,12 @@ describe('ECDH', function() { var sh2 = s2.derive(s1.getPublic()); assert.equal(sh1.toString(16), sh2.toString(16)); + + var sh1 = s1.derive(ecdh.keyFromPublic(s2.getPublic('hex'), 'hex') + .getPublic()); + var sh2 = s2.derive(ecdh.keyFromPublic(s1.getPublic('hex'), 'hex') + .getPublic()); + assert.equal(sh1.toString(16), sh2.toString(16)); }); } diff --git a/test/ecdsa-test.js b/test/ecdsa-test.js index 71c36cd..2a1102e 100644 --- a/test/ecdsa-test.js +++ b/test/ecdsa-test.js @@ -34,15 +34,15 @@ describe('ECDSA', function() { assert(keys.verify(msg, signature), 'On-key verify'); // Load private key from hex - var keys = ecdsa.keyPair(keys.getPrivate('hex'), 'hex'); + var keys = ecdsa.keyFromPrivate(keys.getPrivate('hex'), 'hex'); var signature = ecdsa.sign(msg, keys); assert(ecdsa.verify(msg, signature, keys), 'hex-private verify'); // Load public key from compact hex - var keys = ecdsa.keyPair(keys.getPublic(true, 'hex'), 'hex'); + var keys = ecdsa.keyFromPublic(keys.getPublic(true, 'hex'), 'hex'); // Load public key from hex - var keys = ecdsa.keyPair(keys.getPublic('hex'), 'hex'); + var keys = ecdsa.keyFromPublic(keys.getPublic('hex'), 'hex'); // DER encoding var dsign = signature.toDER('hex'); @@ -55,8 +55,8 @@ describe('ECDSA', function() { assert(!ecdsa.verify(msg, signature, keys), 'Wrong key verify'); // Invalid private key - var keys = ecdsa.keyPair(keys.getPrivate('hex') + keys.getPrivate('hex'), - 'hex'); + var keys = ecdsa.keyFromPrivate(keys.getPrivate('hex') + + keys.getPrivate('hex')); assert(!ecdsa.verify(msg, signature, keys), 'Wrong key verify'); }); } @@ -77,7 +77,7 @@ describe('ECDSA', function() { var sign = ecdsa.sign(dgst, opt.key); assert.equal(sign.r.toString(16), c.r); assert.equal(sign.s.toString(16), c.s); - assert.ok(ecdsa.keyPair(opt.pub).validate().result, + assert.ok(ecdsa.keyFromPublic(opt.pub).validate().result, 'Invalid public key'); assert.ok(ecdsa.verify(dgst, sign, opt.pub), 'Invalid signature');