diff --git a/lib/elliptic/curve/edwards.js b/lib/elliptic/curve/edwards.js index 75c1666..a9889d9 100644 --- a/lib/elliptic/curve/edwards.js +++ b/lib/elliptic/curve/edwards.js @@ -57,7 +57,11 @@ EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { var rhs = this.c2.redSub(this.a.redMul(x2)); var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); - var y = rhs.redMul(lhs.redInvm()).redSqrt(); + var y2 = rhs.redMul(lhs.redInvm()); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + var isOdd = y.fromRed().isOdd(); if (odd && !isOdd || !odd && isOdd) y = y.redNeg(); diff --git a/lib/elliptic/curve/short.js b/lib/elliptic/curve/short.js index 53c40d3..dfe25d0 100644 --- a/lib/elliptic/curve/short.js +++ b/lib/elliptic/curve/short.js @@ -192,6 +192,8 @@ ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); // XXX Is there any way to tell if the number is odd without converting it // to non-red form? diff --git a/lib/elliptic/ec/index.js b/lib/elliptic/ec/index.js index 0a950cc..02deffa 100644 --- a/lib/elliptic/ec/index.js +++ b/lib/elliptic/ec/index.js @@ -208,7 +208,12 @@ EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { return signature.recoveryParam; for (var i = 0; i < 4; i++) { - var Qprime = this.recoverPubKey(e, signature, i); + var Qprime; + try { + Qprime = this.recoverPubKey(e, signature, i); + } catch (e) { + continue; + } if (Qprime.eq(Q)) return i; diff --git a/lib/elliptic/ec/signature.js b/lib/elliptic/ec/signature.js index 9f8776f..09d7213 100644 --- a/lib/elliptic/ec/signature.js +++ b/lib/elliptic/ec/signature.js @@ -16,7 +16,7 @@ function Signature(options, enc) { assert(options.r && options.s, 'Signature without r or s'); this.r = new BN(options.r, 16); this.s = new BN(options.s, 16); - if (options.recoveryParam !== null) + if (options.recoveryParam) this.recoveryParam = options.recoveryParam; else this.recoveryParam = null; diff --git a/test/ecdsa-test.js b/test/ecdsa-test.js index 53bbe7f..b573ff0 100644 --- a/test/ecdsa-test.js +++ b/test/ecdsa-test.js @@ -367,4 +367,19 @@ describe('ECDSA', function() { var r = ec.recoverPubKey(msg, signature, recid); assert(key.getPublic().eq(r), 'the keys should match'); }); + + it('should fail to recover key when no quadratic residue available', + function() { + var ec = new elliptic.ec('secp256k1'); + + var message = + 'f75c6b18a72fabc0f0b888c3da58e004f0af1fe14f7ca5d8c897fe164925d5e9'; + + assert.throws(function() { + ecdsa.recoverPubKey(message, { + r: 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140', + s: '8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3', + }, 0); + }); + }); });