From 2dec1375a17f19e36c1eda1e0a6270071ff45a03 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Sat, 10 May 2014 22:38:05 +1000
Subject: [PATCH] ecdsa: use (r, s) values directly

---
 src/ecdsa.js        | 26 ++------------------------
 src/ecpubkey.js     |  4 ++--
 src/message.js      |  2 +-
 src/transaction.js  | 24 ++++++++++++++++--------
 test/ecdsa.js       |  7 +++----
 test/transaction.js |  4 ++--
 6 files changed, 26 insertions(+), 41 deletions(-)

diff --git a/src/ecdsa.js b/src/ecdsa.js
index 5303c0b..bb70c56 100644
--- a/src/ecdsa.js
+++ b/src/ecdsa.js
@@ -54,30 +54,10 @@ var ecdsa = {
       s = n.subtract(s)
     }
 
-    return ecdsa.serializeSig(r, s)
+    return {r: r, s: s}
   },
 
-  verify: function (hash, sig, pubkey) {
-    var r,s
-    if (Array.isArray(sig) || Buffer.isBuffer(sig)) {
-      var obj = ecdsa.parseSig(sig)
-      r = obj.r
-      s = obj.s
-    } else if ("object" === typeof sig && sig.r && sig.s) {
-      r = sig.r
-      s = sig.s
-    } else {
-      throw new Error("Invalid value for signature")
-    }
-
-    var Q
-    if (pubkey instanceof ECPointFp) {
-      Q = pubkey
-    } else if (Array.isArray(pubkey) || Buffer.isBuffer(pubkey)) {
-      Q = ECPointFp.decodeFrom(ecparams.getCurve(), pubkey)
-    } else {
-      throw new Error("Invalid format for pubkey value, must be byte array or ECPointFp")
-    }
+  verify: function (hash, r, s, Q) {
     var e = BigInteger.fromBuffer(hash)
 
     return ecdsa.verifyRaw(e, r, s, Q)
@@ -140,8 +120,6 @@ var ecdsa = {
    * }
    */
   parseSig: function (buffer) {
-    if (Array.isArray(buffer)) buffer = new Buffer(buffer) // FIXME: transitionary
-
     assert.equal(buffer.readUInt8(0), 0x30, 'Not a DER sequence')
     assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length')
 
diff --git a/src/ecpubkey.js b/src/ecpubkey.js
index bd2e7e8..a5b86bd 100644
--- a/src/ecpubkey.js
+++ b/src/ecpubkey.js
@@ -36,8 +36,8 @@ ECPubKey.prototype.getAddress = function(version) {
   return new Address(crypto.hash160(this.toBuffer()), version)
 }
 
-ECPubKey.prototype.verify = function(hash, sig) {
-  return ecdsa.verify(hash, sig, this.Q)
+ECPubKey.prototype.verify = function(hash, signature) {
+  return ecdsa.verify(hash, signature.r, signature.s, this.Q)
 }
 
 // Export functions
diff --git a/src/message.js b/src/message.js
index 1feaa31..2a72f83 100644
--- a/src/message.js
+++ b/src/message.js
@@ -25,7 +25,7 @@ function sign(key, message, network) {
   network = network || networks.bitcoin
 
   var hash = magicHash(message, network)
-  var sig = ecdsa.parseSig(key.sign(hash))
+  var sig = key.sign(hash)
   var e = BigInteger.fromBuffer(hash)
   var i = ecdsa.calcPubKeyRecoveryParam(e, sig.r, sig.s, key.pub.Q)
 
diff --git a/src/transaction.js b/src/transaction.js
index bfbbe0e..09db26d 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -364,27 +364,35 @@ Transaction.prototype.sign = function(index, key, type) {
   this.setScriptSig(index, scriptSig)
 }
 
-Transaction.prototype.signScriptSig = function(index, script, key, type) {
+Transaction.prototype.signScriptSig = function(index, scriptPubKey, key, type) {
   type = type || SIGHASH_ALL
 
   assert((index >= 0), 'Invalid vin index')
-  assert(script instanceof Script, 'Invalid Script object')
+  assert(scriptPubKey instanceof Script, 'Invalid Script object')
   assert(key instanceof ECKey, 'Invalid private key')
 //  assert.equal(type & 0x7F, type, 'Invalid type') // TODO
 
-  var hash = this.hashForSignature(script, index, type)
-  return key.sign(hash).concat([type])
+  var hash = this.hashForSignature(scriptPubKey, index, type)
+  var sig = key.sign(hash)
+  var DERsig = ecdsa.serializeSig(sig.r, sig.s)
+
+  return Buffer.concat([
+    new Buffer(DERsig),
+    new Buffer([type])
+  ])
 }
 
 Transaction.prototype.setScriptSig = function(index, script) {
   this.ins[index].script = script
 }
 
-Transaction.prototype.validateSig = function(index, script, pub, sig) {
-  var type = sig[sig.length - 1]
-  var hash = this.hashForSignature(script, index, type)
+Transaction.prototype.validateSig = function(index, script, pub, DERsig) {
+  var type = DERsig.readUInt8(DERsig.length - 1)
+  DERsig = DERsig.slice(0, -1)
+
+  var hash = this.hashForSignature(script, index, type)
+  var sig = ecdsa.parseSig(DERsig)
 
-  sig = sig.slice(0, -1)
   return pub.verify(hash, sig)
 }
 
diff --git a/test/ecdsa.js b/test/ecdsa.js
index ad9806d..bc9e49d 100644
--- a/test/ecdsa.js
+++ b/test/ecdsa.js
@@ -46,7 +46,7 @@ describe('ecdsa', function() {
         var D = BigInteger.fromHex(f.D)
         var priv = new ECKey(D)
         var hash = crypto.sha256(f.message)
-        var sig = ecdsa.parseSig(priv.sign(hash))
+        var sig = priv.sign(hash)
 
         assert.equal(sig.r.toString(), f.signature.r)
         assert.equal(sig.s.toString(), f.signature.s)
@@ -56,12 +56,11 @@ describe('ecdsa', function() {
     it('should sign with low S value', function() {
       var priv = ECKey.makeRandom()
       var hash = crypto.sha256('Vires in numeris')
-      var signature = priv.sign(hash)
-      var psig = ecdsa.parseSig(signature)
+      var sig = priv.sign(hash)
 
       // See BIP62 for more information
       var N_OVER_TWO = ecparams.getN().shiftRight(1)
-      assert(psig.s.compareTo(N_OVER_TWO) <= 0)
+      assert(sig.s.compareTo(N_OVER_TWO) <= 0)
     })
   })
 
diff --git a/test/transaction.js b/test/transaction.js
index 9f33cc4..e22f7f8 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -197,7 +197,7 @@ describe('Transaction', function() {
         tx.sign(0, key)
 
         var script = prevTx.outs[0].script
-        var sig = tx.ins[0].script.chunks[0]
+        var sig = new Buffer(tx.ins[0].script.chunks[0])
 
         assert.equal(tx.validateSig(0, script, key.pub, sig), true)
       })
@@ -213,7 +213,7 @@ describe('Transaction', function() {
       it('returns true for valid signature', function(){
         var key = ECKey.fromWIF('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb')
         var script = prevTx.outs[0].script
-        var sig = validTx.ins[0].script.chunks[0]
+        var sig = new Buffer(validTx.ins[0].script.chunks[0])
 
         assert.equal(validTx.validateSig(0, script, key.pub, sig), true)
       })