ecdsa: always use signature object
This commit is contained in:
parent
52217ea262
commit
58fd12e66d
6 changed files with 121 additions and 95 deletions
66
src/ecdsa.js
66
src/ecdsa.js
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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])
|
||||
])
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue