ecdsa: use (r, s) values directly
This commit is contained in:
parent
8d7408202f
commit
2dec1375a1
6 changed files with 26 additions and 41 deletions
26
src/ecdsa.js
26
src/ecdsa.js
|
@ -54,30 +54,10 @@ var ecdsa = {
|
||||||
s = n.subtract(s)
|
s = n.subtract(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ecdsa.serializeSig(r, s)
|
return {r: r, s: s}
|
||||||
},
|
},
|
||||||
|
|
||||||
verify: function (hash, sig, pubkey) {
|
verify: function (hash, r, s, Q) {
|
||||||
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")
|
|
||||||
}
|
|
||||||
var e = BigInteger.fromBuffer(hash)
|
var e = BigInteger.fromBuffer(hash)
|
||||||
|
|
||||||
return ecdsa.verifyRaw(e, r, s, Q)
|
return ecdsa.verifyRaw(e, r, s, Q)
|
||||||
|
@ -140,8 +120,6 @@ var ecdsa = {
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
parseSig: function (buffer) {
|
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(0), 0x30, 'Not a DER sequence')
|
||||||
assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length')
|
assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length')
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ ECPubKey.prototype.getAddress = function(version) {
|
||||||
return new Address(crypto.hash160(this.toBuffer()), version)
|
return new Address(crypto.hash160(this.toBuffer()), version)
|
||||||
}
|
}
|
||||||
|
|
||||||
ECPubKey.prototype.verify = function(hash, sig) {
|
ECPubKey.prototype.verify = function(hash, signature) {
|
||||||
return ecdsa.verify(hash, sig, this.Q)
|
return ecdsa.verify(hash, signature.r, signature.s, this.Q)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export functions
|
// Export functions
|
||||||
|
|
|
@ -25,7 +25,7 @@ function sign(key, message, network) {
|
||||||
network = network || networks.bitcoin
|
network = network || networks.bitcoin
|
||||||
|
|
||||||
var hash = magicHash(message, network)
|
var hash = magicHash(message, network)
|
||||||
var sig = ecdsa.parseSig(key.sign(hash))
|
var sig = key.sign(hash)
|
||||||
var e = BigInteger.fromBuffer(hash)
|
var e = BigInteger.fromBuffer(hash)
|
||||||
var i = ecdsa.calcPubKeyRecoveryParam(e, sig.r, sig.s, key.pub.Q)
|
var i = ecdsa.calcPubKeyRecoveryParam(e, sig.r, sig.s, key.pub.Q)
|
||||||
|
|
||||||
|
|
|
@ -364,27 +364,35 @@ Transaction.prototype.sign = function(index, key, type) {
|
||||||
this.setScriptSig(index, scriptSig)
|
this.setScriptSig(index, scriptSig)
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction.prototype.signScriptSig = function(index, script, key, type) {
|
Transaction.prototype.signScriptSig = function(index, scriptPubKey, key, type) {
|
||||||
type = type || SIGHASH_ALL
|
type = type || SIGHASH_ALL
|
||||||
|
|
||||||
assert((index >= 0), 'Invalid vin index')
|
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(key instanceof ECKey, 'Invalid private key')
|
||||||
// assert.equal(type & 0x7F, type, 'Invalid type') // TODO
|
// assert.equal(type & 0x7F, type, 'Invalid type') // TODO
|
||||||
|
|
||||||
var hash = this.hashForSignature(script, index, type)
|
var hash = this.hashForSignature(scriptPubKey, index, type)
|
||||||
return key.sign(hash).concat([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) {
|
Transaction.prototype.setScriptSig = function(index, script) {
|
||||||
this.ins[index].script = script
|
this.ins[index].script = script
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction.prototype.validateSig = function(index, script, pub, sig) {
|
Transaction.prototype.validateSig = function(index, script, pub, DERsig) {
|
||||||
var type = sig[sig.length - 1]
|
var type = DERsig.readUInt8(DERsig.length - 1)
|
||||||
var hash = this.hashForSignature(script, index, type)
|
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)
|
return pub.verify(hash, sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ describe('ecdsa', function() {
|
||||||
var D = BigInteger.fromHex(f.D)
|
var D = BigInteger.fromHex(f.D)
|
||||||
var priv = new ECKey(D)
|
var priv = new ECKey(D)
|
||||||
var hash = crypto.sha256(f.message)
|
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.r.toString(), f.signature.r)
|
||||||
assert.equal(sig.s.toString(), f.signature.s)
|
assert.equal(sig.s.toString(), f.signature.s)
|
||||||
|
@ -56,12 +56,11 @@ describe('ecdsa', function() {
|
||||||
it('should sign with low S value', function() {
|
it('should sign with low S value', function() {
|
||||||
var priv = ECKey.makeRandom()
|
var priv = ECKey.makeRandom()
|
||||||
var hash = crypto.sha256('Vires in numeris')
|
var hash = crypto.sha256('Vires in numeris')
|
||||||
var signature = priv.sign(hash)
|
var sig = priv.sign(hash)
|
||||||
var psig = ecdsa.parseSig(signature)
|
|
||||||
|
|
||||||
// See BIP62 for more information
|
// See BIP62 for more information
|
||||||
var N_OVER_TWO = ecparams.getN().shiftRight(1)
|
var N_OVER_TWO = ecparams.getN().shiftRight(1)
|
||||||
assert(psig.s.compareTo(N_OVER_TWO) <= 0)
|
assert(sig.s.compareTo(N_OVER_TWO) <= 0)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,7 @@ describe('Transaction', function() {
|
||||||
tx.sign(0, key)
|
tx.sign(0, key)
|
||||||
|
|
||||||
var script = prevTx.outs[0].script
|
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)
|
assert.equal(tx.validateSig(0, script, key.pub, sig), true)
|
||||||
})
|
})
|
||||||
|
@ -213,7 +213,7 @@ describe('Transaction', function() {
|
||||||
it('returns true for valid signature', function(){
|
it('returns true for valid signature', function(){
|
||||||
var key = ECKey.fromWIF('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb')
|
var key = ECKey.fromWIF('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb')
|
||||||
var script = prevTx.outs[0].script
|
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)
|
assert.equal(validTx.validateSig(0, script, key.pub, sig), true)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Reference in a new issue