diff --git a/src/ecdsa.js b/src/ecdsa.js index cb1013c..5303c0b 100644 --- a/src/ecdsa.js +++ b/src/ecdsa.js @@ -205,7 +205,7 @@ var ecdsa = { * * http://www.secg.org/download/aid-780/sec1-v2.pdf */ - recoverPubKey: function (r, s, hash, i) { + recoverPubKey: function (e, r, s, i) { assert.strictEqual(i & 3, i, 'The recovery param is more than two bits') // A set LSB signifies that the y-coordinate is odd @@ -243,15 +243,16 @@ var ecdsa = { var R = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y)) R.validate() - // 1.5 Compute e from M - var e = BigInteger.fromBuffer(hash) + // 1.5 Compute -e from e var eNeg = e.negate().mod(n) - // 1.6 Compute Q = r^-1 (sR - eG) + // 1.6 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) var rInv = r.modInverse(n) - var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv) + var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv) Q.validate() + if (!ecdsa.verifyRaw(e, r, s, Q)) { throw new Error("Pubkey recovery unsuccessful") } @@ -270,16 +271,16 @@ var ecdsa = { * This function simply tries all four cases and returns the value * that resulted in a successful pubkey recovery. */ - calcPubKeyRecoveryParam: function (origPubKey, r, s, hash) { + calcPubKeyRecoveryParam: function (e, r, s, Q) { for (var i = 0; i < 4; i++) { - var pubKey = ecdsa.recoverPubKey(r, s, hash, i) + var Qprime = ecdsa.recoverPubKey(e, r, s, i) - if (pubKey.equals(origPubKey)) { + if (Qprime.equals(Q)) { return i } } - throw new Error("Unable to find valid recovery factor") + throw new Error('Unable to find valid recovery factor') } } diff --git a/src/message.js b/src/message.js index b7d545b..1feaa31 100644 --- a/src/message.js +++ b/src/message.js @@ -1,5 +1,6 @@ /// Implements Bitcoin's feature for signing arbitrary messages. var Address = require('./address') +var BigInteger = require('bigi') var bufferutils = require('./bufferutils') var crypto = require('./crypto') var ecdsa = require('./ecdsa') @@ -25,7 +26,8 @@ function sign(key, message, network) { var hash = magicHash(message, network) var sig = ecdsa.parseSig(key.sign(hash)) - var i = ecdsa.calcPubKeyRecoveryParam(key.pub.Q, sig.r, sig.s, hash) + var e = BigInteger.fromBuffer(hash) + var i = ecdsa.calcPubKeyRecoveryParam(e, sig.r, sig.s, key.pub.Q) return ecdsa.serializeSigCompact(sig.r, sig.s, i, key.pub.compressed) } @@ -40,7 +42,8 @@ function verify(address, compactSig, message, network) { var hash = magicHash(message, network) var sig = ecdsa.parseSigCompact(compactSig) - var Q = ecdsa.recoverPubKey(sig.r, sig.s, hash, sig.i) + var e = BigInteger.fromBuffer(hash) + var Q = ecdsa.recoverPubKey(e, sig.r, sig.s, sig.i) var pubKey = new ECPubKey(Q, sig.compressed) return pubKey.getAddress(address.version).toString() === address.toString() diff --git a/test/ecdsa.js b/test/ecdsa.js index 9decb27..ad9806d 100644 --- a/test/ecdsa.js +++ b/test/ecdsa.js @@ -32,8 +32,9 @@ describe('ecdsa', function() { var obj = ecdsa.parseSigCompact(signature) var hash = message.magicHash('1111', networks.bitcoin) + var e = BigInteger.fromBuffer(hash) - var pubKey = new ECPubKey(ecdsa.recoverPubKey(obj.r, obj.s, hash, obj.i)) + var pubKey = new ECPubKey(ecdsa.recoverPubKey(e, obj.r, obj.s, obj.i)) assert.equal(pubKey.toHex(), '02e8fcf4d749b35879bc1f3b14b49e67ab7301da3558c5a9b74a54f1e6339c334c') })