ecdsa: always use signature object

This commit is contained in:
Daniel Cousens 2014-05-24 16:25:38 +10:00
parent 52217ea262
commit 58fd12e66d
6 changed files with 121 additions and 95 deletions

View file

@ -54,23 +54,21 @@ function sign(ecparams, hash, D) {
return {r: r, s: s}
}
function verify(ecparams, hash, r, s, Q) {
function verify(ecparams, hash, signature, Q) {
var e = BigInteger.fromBuffer(hash)
return verifyRaw(ecparams, e, r, s, Q)
return verifyRaw(ecparams, e, signature, Q)
}
function verifyRaw(ecparams, e, r, s, Q) {
function verifyRaw(ecparams, e, signature, Q) {
var n = ecparams.getN()
var G = ecparams.getG()
if (r.signum() === 0 || r.compareTo(n) >= 0) {
return false
}
var r = signature.r
var s = signature.s
if (s.signum() === 0 || s.compareTo(n) >= 0) {
return false
}
if (r.signum() === 0 || r.compareTo(n) >= 0) return false
if (s.signum() === 0 || s.compareTo(n) >= 0) return false
var c = s.modInverse(n)
@ -88,9 +86,9 @@ function verifyRaw(ecparams, e, r, s, Q) {
*
* Takes two BigIntegers representing r and s and returns a byte array.
*/
function serializeSig(r, s) {
var rBa = r.toDERInteger()
var sBa = s.toDERInteger()
function serializeSig(signature) {
var rBa = signature.r.toDERInteger()
var sBa = signature.s.toDERInteger()
var sequence = []
sequence.push(0x02); // INTEGER
@ -136,7 +134,7 @@ function parseSig(buffer) {
}
}
function serializeSigCompact(r, s, i, compressed) {
function serializeSigCompact(signature, i, compressed) {
if (compressed) {
i += 4
}
@ -145,8 +143,9 @@ function serializeSigCompact(r, s, i, compressed) {
var buffer = new Buffer(65)
buffer.writeUInt8(i, 0)
r.toBuffer(32).copy(buffer, 1)
s.toBuffer(32).copy(buffer, 33)
signature.r.toBuffer(32).copy(buffer, 1)
signature.s.toBuffer(32).copy(buffer, 33)
return buffer
}
@ -166,8 +165,10 @@ function parseSigCompact(buffer) {
var s = BigInteger.fromBuffer(buffer.slice(33))
return {
r: r,
s: s,
signature: {
r: r,
s: s
},
i: i,
compressed: compressed
}
@ -181,9 +182,12 @@ function parseSigCompact(buffer) {
*
* http://www.secg.org/download/aid-780/sec1-v2.pdf
*/
function recoverPubKey(ecparams, e, r, s, i) {
function recoverPubKey(ecparams, e, signature, i) {
assert.strictEqual(i & 3, i, 'The recovery param is more than two bits')
var r = signature.r
var s = signature.s
// A set LSB signifies that the y-coordinate is odd
// By reduction, the y-coordinate is even if it is clear
var isYEven = !(i & 1)
@ -229,7 +233,7 @@ function recoverPubKey(ecparams, e, r, s, i) {
var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv)
Q.validate()
if (!verifyRaw(ecparams, e, r, s, Q)) {
if (!verifyRaw(ecparams, e, signature, Q)) {
throw new Error("Pubkey recovery unsuccessful")
}
@ -247,9 +251,9 @@ function recoverPubKey(ecparams, e, r, s, i) {
* This function simply tries all four cases and returns the value
* that resulted in a successful pubkey recovery.
*/
function calcPubKeyRecoveryParam(ecparams, e, r, s, Q) {
function calcPubKeyRecoveryParam(ecparams, e, signature, Q) {
for (var i = 0; i < 4; i++) {
var Qprime = recoverPubKey(ecparams, e, r, s, i)
var Qprime = recoverPubKey(ecparams, e, signature, i)
if (Qprime.equals(Q)) {
return i
@ -260,14 +264,14 @@ function calcPubKeyRecoveryParam(ecparams, e, r, s, Q) {
}
module.exports = {
calcPubKeyRecoveryParam: calcPubKeyRecoveryParam,
deterministicGenerateK: deterministicGenerateK,
recoverPubKey: recoverPubKey,
sign: sign,
verify: verify,
verifyRaw: verifyRaw,
serializeSig: serializeSig,
parseSig: parseSig,
serializeSigCompact: serializeSigCompact,
parseSigCompact: parseSigCompact
calcPubKeyRecoveryParam: calcPubKeyRecoveryParam,
deterministicGenerateK: deterministicGenerateK,
recoverPubKey: recoverPubKey,
sign: sign,
verify: verify,
verifyRaw: verifyRaw,
serializeSig: serializeSig,
parseSig: parseSig,
serializeSigCompact: serializeSigCompact,
parseSigCompact: parseSigCompact
}

View file

@ -37,7 +37,7 @@ ECPubKey.prototype.getAddress = function(version) {
}
ECPubKey.prototype.verify = function(hash, signature) {
return ecdsa.verify(ecparams, hash, signature.r, signature.s, this.Q)
return ecdsa.verify(ecparams, hash, signature, this.Q)
}
// Export functions

View file

@ -28,11 +28,11 @@ function sign(key, message, network) {
network = network || networks.bitcoin
var hash = magicHash(message, network)
var sig = key.sign(hash)
var signature = key.sign(hash)
var e = BigInteger.fromBuffer(hash)
var i = ecdsa.calcPubKeyRecoveryParam(ecparams, e, sig.r, sig.s, key.pub.Q)
var i = ecdsa.calcPubKeyRecoveryParam(ecparams, e, signature, key.pub.Q)
return ecdsa.serializeSigCompact(sig.r, sig.s, i, key.pub.compressed)
return ecdsa.serializeSigCompact(signature, i, key.pub.compressed)
}
// TODO: network could be implied from address
@ -44,11 +44,11 @@ function verify(address, compactSig, message, network) {
network = network || networks.bitcoin
var hash = magicHash(message, network)
var sig = ecdsa.parseSigCompact(compactSig)
var parsed = ecdsa.parseSigCompact(compactSig)
var e = BigInteger.fromBuffer(hash)
var Q = ecdsa.recoverPubKey(ecparams, e, sig.r, sig.s, sig.i)
var Q = ecdsa.recoverPubKey(ecparams, e, parsed.signature, parsed.i)
var pubKey = new ECPubKey(Q, sig.compressed)
var pubKey = new ECPubKey(Q, parsed.compressed)
return pubKey.getAddress(address.version).toString() === address.toString()
}

View file

@ -373,11 +373,11 @@ Transaction.prototype.signScriptSig = function(index, scriptPubKey, key, type) {
// assert.equal(type & 0x7F, type, 'Invalid type') // TODO
var hash = this.hashForSignature(scriptPubKey, index, type)
var sig = key.sign(hash)
var DERsig = ecdsa.serializeSig(sig.r, sig.s)
var signature = key.sign(hash)
var DERencoded = ecdsa.serializeSig(signature)
return Buffer.concat([
new Buffer(DERsig),
new Buffer(DERencoded),
new Buffer([type])
])
}