From eb3d9a25f7b7dfddd0268f5dda983e572836a140 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sun, 15 Jun 2014 16:44:52 +1000 Subject: [PATCH] ecdsa: moved all signature encoding to ECSignature --- src/ecdsa.js | 105 +-------------------------- src/ecsignature.js | 102 ++++++++++++++++++++++++++ src/index.js | 1 + src/message.js | 17 +++-- src/transaction.js | 20 ++---- test/ecdsa.js | 109 ++++------------------------ test/ecsignature.js | 82 +++++++++++++++++++++ test/fixtures/ecdsa.json | 85 ++-------------------- test/fixtures/ecsignature.json | 126 +++++++++++++++++++++++++++++++++ 9 files changed, 350 insertions(+), 297 deletions(-) create mode 100644 src/ecsignature.js create mode 100644 test/ecsignature.js create mode 100644 test/fixtures/ecsignature.json diff --git a/src/ecdsa.js b/src/ecdsa.js index 76e779e..e9769ba 100644 --- a/src/ecdsa.js +++ b/src/ecdsa.js @@ -2,6 +2,7 @@ var assert = require('assert') var crypto = require('./crypto') var BigInteger = require('bigi') +var ECSignature = require('./ecsignature') var Point = require('ecurve').Point function deterministicGenerateK(curve, hash, d) { @@ -51,7 +52,7 @@ function sign(curve, hash, d) { s = n.subtract(s) } - return {r: r, s: s} + return new ECSignature(r, s) } function verify(curve, hash, signature, Q) { @@ -81,102 +82,6 @@ function verifyRaw(curve, e, signature, Q) { return v.equals(r) } -/** - * Serialize a signature into DER format. - * - * Takes two BigIntegers representing r and s and returns a byte array. - */ -function serializeSig(signature) { - var rBa = signature.r.toDERInteger() - var sBa = signature.s.toDERInteger() - - var sequence = [] - sequence.push(0x02) // INTEGER - sequence.push(rBa.length) - sequence = sequence.concat(rBa) - - sequence.push(0x02) // INTEGER - sequence.push(sBa.length) - sequence = sequence.concat(sBa) - - sequence.unshift(sequence.length) - sequence.unshift(0x30) // SEQUENCE - - return new Buffer(sequence) -} - -/** - * Parses a buffer containing a DER-encoded signature. - * - * This function will return an object of the form: - * - * { - * r: BigInteger, - * s: BigInteger - * } - */ -function parseSig(buffer) { - 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(2), 0x02, 'Expected a DER integer') - var rLen = buffer.readUInt8(3) - var rB = buffer.slice(4, 4 + rLen) - - var offset = 4 + rLen - assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)') - var sLen = buffer.readUInt8(1 + offset) - var sB = buffer.slice(2 + offset) - offset += 2 + sLen - - assert.equal(offset, buffer.length, 'Invalid DER encoding') - - return { - r: BigInteger.fromDERInteger(rB), - s: BigInteger.fromDERInteger(sB) - } -} - -function serializeSigCompact(signature, i, compressed) { - if (compressed) { - i += 4 - } - - i += 27 - - var buffer = new Buffer(65) - buffer.writeUInt8(i, 0) - - signature.r.toBuffer(32).copy(buffer, 1) - signature.s.toBuffer(32).copy(buffer, 33) - - return buffer -} - -function parseSigCompact(buffer) { - assert.equal(buffer.length, 65, 'Invalid signature length') - var i = buffer.readUInt8(0) - 27 - - // At most 3 bits - assert.equal(i, i & 7, 'Invalid signature parameter') - var compressed = !!(i & 4) - - // Recovery param only - i = i & 3 - - var r = BigInteger.fromBuffer(buffer.slice(1, 33)) - var s = BigInteger.fromBuffer(buffer.slice(33)) - - return { - signature: { - r: r, - s: s - }, - i: i, - compressed: compressed - } -} - /** * Recover a public key from a signature. * @@ -269,9 +174,5 @@ module.exports = { recoverPubKey: recoverPubKey, sign: sign, verify: verify, - verifyRaw: verifyRaw, - serializeSig: serializeSig, - parseSig: parseSig, - serializeSigCompact: serializeSigCompact, - parseSigCompact: parseSigCompact + verifyRaw: verifyRaw } diff --git a/src/ecsignature.js b/src/ecsignature.js new file mode 100644 index 0000000..3b5dd53 --- /dev/null +++ b/src/ecsignature.js @@ -0,0 +1,102 @@ +var assert = require('assert') + +var BigInteger = require('bigi') + +function ECSignature(r, s) { + assert(r instanceof BigInteger, 'Expected BigInteger, got ' + r) + assert(s instanceof BigInteger, 'Expected BigInteger, got ' + s) + this.r = r + this.s = s +} + +// Import operations +ECSignature.fromCompact = function(buffer) { + assert.equal(buffer.length, 65, 'Invalid signature length') + var i = buffer.readUInt8(0) - 27 + + // At most 3 bits + assert.equal(i, i & 7, 'Invalid signature parameter') + var compressed = !!(i & 4) + + // Recovery param only + i = i & 3 + + var r = BigInteger.fromBuffer(buffer.slice(1, 33)) + var s = BigInteger.fromBuffer(buffer.slice(33)) + + return { + compressed: compressed, + i: i, + signature: new ECSignature(r, s) + } +} + +ECSignature.fromDER = function(buffer) { + 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(2), 0x02, 'Expected a DER integer') + var rLen = buffer.readUInt8(3) + var rB = buffer.slice(4, 4 + rLen) + + var offset = 4 + rLen + assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)') + var sLen = buffer.readUInt8(1 + offset) + var sB = buffer.slice(2 + offset) + offset += 2 + sLen + + assert.equal(offset, buffer.length, 'Invalid DER encoding') + var r = BigInteger.fromDERInteger(rB) + var s = BigInteger.fromDERInteger(sB) + + return new ECSignature(r, s) +} + +ECSignature.fromScriptSignature = function(buffer) { + return { + signature: ECSignature.fromDER(buffer.slice(0, -1)), + hashType: buffer.readUInt8(buffer.length - 1) + } +} + +// Export operations +ECSignature.prototype.toCompact = function(i, compressed) { + if (compressed) i += 4 + i += 27 + + var buffer = new Buffer(65) + buffer.writeUInt8(i, 0) + + this.r.toBuffer(32).copy(buffer, 1) + this.s.toBuffer(32).copy(buffer, 33) + + return buffer +} + +ECSignature.prototype.toDER = function() { + var rBa = this.r.toDERInteger() + var sBa = this.s.toDERInteger() + + var sequence = [] + sequence.push(0x02) // INTEGER + sequence.push(rBa.length) + sequence = sequence.concat(rBa) + + sequence.push(0x02) // INTEGER + sequence.push(sBa.length) + sequence = sequence.concat(sBa) + + sequence.unshift(sequence.length) + sequence.unshift(0x30) // SEQUENCE + + return new Buffer(sequence) +} + +ECSignature.prototype.toScriptSignature = function(hashType) { + var hashTypeBuffer = new Buffer(1) + hashTypeBuffer.writeUInt8(hashType, 0) + + return Buffer.concat([this.toDER(), hashTypeBuffer]) +} + +module.exports = ECSignature diff --git a/src/index.js b/src/index.js index 2b9ae4b..def766c 100644 --- a/src/index.js +++ b/src/index.js @@ -8,6 +8,7 @@ module.exports = { ecdsa: require('./ecdsa'), ECKey: require('./eckey'), ECPubKey: require('./ecpubkey'), + ECSignature: require('./ecsignature'), Message: require('./message'), opcodes: require('./opcodes'), HDNode: require('./hdnode'), diff --git a/src/message.js b/src/message.js index a70b9a2..2163fc8 100644 --- a/src/message.js +++ b/src/message.js @@ -8,6 +8,7 @@ var networks = require('./networks') var Address = require('./address') var ECPubKey = require('./ecpubkey') +var ECSignature = require('./ecsignature') var ecurve = require('ecurve') var ecparams = ecurve.getCurveByName('secp256k1') @@ -18,32 +19,30 @@ function magicHash(message, network) { var lengthBuffer = new Buffer(bufferutils.varIntSize(messageBuffer.length)) bufferutils.writeVarInt(lengthBuffer, messageBuffer.length, 0) - var buffer = Buffer.concat([ - magicPrefix, lengthBuffer, messageBuffer - ]) + var buffer = Buffer.concat([magicPrefix, lengthBuffer, messageBuffer]) return crypto.hash256(buffer) } -function sign(key, message, network) { +function sign(privKey, message, network) { network = network || networks.bitcoin var hash = magicHash(message, network) - var signature = key.sign(hash) + var signature = privKey.sign(hash) var e = BigInteger.fromBuffer(hash) - var i = ecdsa.calcPubKeyRecoveryParam(ecparams, e, signature, key.pub.Q) + var i = ecdsa.calcPubKeyRecoveryParam(ecparams, e, signature, privKey.pub.Q) - return ecdsa.serializeSigCompact(signature, i, key.pub.compressed) + return signature.toCompact(i, privKey.pub.compressed) } // TODO: network could be implied from address -function verify(address, compactSig, message, network) { +function verify(address, signatureBuffer, message, network) { if (address instanceof Address) { address = address.toString() } network = network || networks.bitcoin var hash = magicHash(message, network) - var parsed = ecdsa.parseSigCompact(compactSig) + var parsed = ECSignature.fromCompact(signatureBuffer) var e = BigInteger.fromBuffer(hash) var Q = ecdsa.recoverPubKey(ecparams, e, parsed.signature, parsed.i) diff --git a/src/transaction.js b/src/transaction.js index 65c0a59..c9c3e08 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -1,12 +1,12 @@ var assert = require('assert') var bufferutils = require('./bufferutils') var crypto = require('./crypto') -var ecdsa = require('./ecdsa') var opcodes = require('./opcodes') var scripts = require('./scripts') var Address = require('./address') var ECKey = require('./eckey') +var ECSignature = require('./ecsignature') var Script = require('./script') var DEFAULT_SEQUENCE = 0xffffffff @@ -301,16 +301,11 @@ Transaction.prototype.sign = function(index, privKey, hashType) { Transaction.prototype.signInput = function(index, prevOutScript, privKey, hashType) { hashType = hashType || SIGHASH_ALL - assert(privKey instanceof ECKey, 'Expected ECKey, got ' + privKey) var hash = this.hashForSignature(prevOutScript, index, hashType) var signature = privKey.sign(hash) - var DERencoded = ecdsa.serializeSig(signature) - return Buffer.concat([ - new Buffer(DERencoded), - new Buffer([hashType]) - ]) + return signature.toScriptSignature(hashType) } Transaction.prototype.setInputScript = function(index, script) { @@ -318,14 +313,11 @@ Transaction.prototype.setInputScript = function(index, script) { } // FIXME: could be validateInput(index, prevTxOut, pub) -Transaction.prototype.validateInput = function(index, prevOutScript, pubKey, DERsig) { - var type = DERsig.readUInt8(DERsig.length - 1) - DERsig = DERsig.slice(0, -1) +Transaction.prototype.validateInput = function(index, prevOutScript, pubKey, buffer) { + var parsed = ECSignature.fromScriptSignature(buffer) + var hash = this.hashForSignature(prevOutScript, index, parsed.hashType) - var hash = this.hashForSignature(prevOutScript, index, type) - var signature = ecdsa.parseSig(DERsig) - - return pubKey.verify(hash, signature) + return pubKey.verify(hash, parsed.signature) } module.exports = Transaction diff --git a/test/ecdsa.js b/test/ecdsa.js index 4b2b1f1..d5a7d0d 100644 --- a/test/ecdsa.js +++ b/test/ecdsa.js @@ -5,6 +5,7 @@ var message = require('../src/message') var networks = require('../src/networks') var BigInteger = require('bigi') +var ECSignature = require('../src/ecsignature') var ecurve = require('ecurve') var curve = ecurve.getCurveByName('secp256k1') @@ -35,7 +36,7 @@ describe('ecdsa', function() { } var h1 = crypto.sha256(f.message) var e = BigInteger.fromBuffer(h1) - var Qprime = ecdsa.recoverPubKey(curve, e, signature, f.compact.i) + var Qprime = ecdsa.recoverPubKey(curve, e, signature, f.i) assert(Qprime.equals(Q)) }) @@ -45,8 +46,8 @@ describe('ecdsa', function() { var hash = message.magicHash('1111', networks.bitcoin) var e = BigInteger.fromBuffer(hash) - var signature = new Buffer('INcvXVVEFyIfHLbDX+xoxlKFn3Wzj9g0UbhObXdMq+YMKC252o5RHFr0/cKdQe1WsBLUBi4morhgZ77obDJVuV0=', 'base64') - var parsed = ecdsa.parseSigCompact(signature) + var signatureBuffer = new Buffer('INcvXVVEFyIfHLbDX+xoxlKFn3Wzj9g0UbhObXdMq+YMKC252o5RHFr0/cKdQe1WsBLUBi4morhgZ77obDJVuV0=', 'base64') + var signature = ECSignature.fromCompact(signatureBuffer).signature var points = [ '03e3a8c44a8bf712f1fbacee274fb19c0239b1a9e877eff0075ea335f2be8ff380', '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', @@ -56,7 +57,7 @@ describe('ecdsa', function() { points.forEach(function(expectedHex, i) { it('recovers an expected point for i of ' + i, function() { - var Qprime = ecdsa.recoverPubKey(curve, e, parsed.signature, i) + var Qprime = ecdsa.recoverPubKey(curve, e, signature, i) var QprimeHex = Qprime.getEncoded().toString('hex') assert.equal(QprimeHex, expectedHex) @@ -67,10 +68,7 @@ describe('ecdsa', function() { fixtures.invalid.recoverPubKey.forEach(function(f) { it('throws on ' + f.description, function() { var e = BigInteger.fromHex(f.e) - var signature = { - r: new BigInteger(f.signature.r), - s: new BigInteger(f.signature.s) - } + var signature = new ECSignature(new BigInteger(f.signature.r), new BigInteger(f.signature.s)) assert.throws(function() { ecdsa.recoverPubKey(curve, e, signature, f.i) @@ -105,13 +103,12 @@ describe('ecdsa', function() { fixtures.valid.forEach(function(f) { it('verifies a valid signature for \"' + f.message + '\"', function() { var d = BigInteger.fromHex(f.d) - var Q = curve.params.G.multiply(d) - - var signature = { - r: new BigInteger(f.signature.r), - s: new BigInteger(f.signature.s) - } var e = BigInteger.fromBuffer(crypto.sha256(f.message)) + var signature = new ECSignature( + new BigInteger(f.signature.r), + new BigInteger(f.signature.s) + ) + var Q = curve.params.G.multiply(d) assert(ecdsa.verifyRaw(curve, e, signature, Q)) }) @@ -121,90 +118,14 @@ describe('ecdsa', function() { it('fails to verify with ' + f.description, function() { var d = BigInteger.fromHex(f.d) var e = BigInteger.fromHex(f.e) - var signature = { - r: new BigInteger(f.signature.r), - s: new BigInteger(f.signature.s) - } + var signature = new ECSignature( + new BigInteger(f.signature.r), + new BigInteger(f.signature.s) + ) var Q = curve.params.G.multiply(d) assert.equal(ecdsa.verifyRaw(curve, e, signature, Q), false) }) }) }) - - describe('serializeSig', function() { - it('encodes a DER signature', function() { - fixtures.valid.forEach(function(f) { - var signature = { - r: new BigInteger(f.signature.r), - s: new BigInteger(f.signature.s) - } - - var signature = new Buffer(ecdsa.serializeSig(signature)) - assert.equal(signature.toString('hex'), f.DER) - }) - }) - }) - - describe('parseSig', function() { - it('decodes the correct signature', function() { - fixtures.valid.forEach(function(f) { - var buffer = new Buffer(f.DER, 'hex') - var signature = ecdsa.parseSig(buffer) - - assert.equal(signature.r.toString(), f.signature.r) - assert.equal(signature.s.toString(), f.signature.s) - }) - }) - - fixtures.invalid.DER.forEach(function(f) { - it('throws on ' + f.hex, function() { - var buffer = new Buffer(f.hex, 'hex') - - assert.throws(function() { - ecdsa.parseSig(buffer) - }, new RegExp(f.exception)) - }) - }) - }) - - describe('serializeSigCompact', function() { - fixtures.valid.forEach(function(f) { - it('encodes ' + f.compact.hex + ' correctly', function() { - var signature = { - r: new BigInteger(f.signature.r), - s: new BigInteger(f.signature.s) - } - var i = f.compact.i - var compressed = f.compact.compressed - - var signature = ecdsa.serializeSigCompact(signature, i, compressed) - assert.equal(signature.toString('hex'), f.compact.hex) - }) - }) - }) - - describe('parseSigCompact', function() { - fixtures.valid.forEach(function(f) { - it('decodes ' + f.compact.hex + ' correctly', function() { - var buffer = new Buffer(f.compact.hex, 'hex') - var parsed = ecdsa.parseSigCompact(buffer) - - assert.equal(parsed.signature.r.toString(), f.signature.r) - assert.equal(parsed.signature.s.toString(), f.signature.s) - assert.equal(parsed.i, f.compact.i) - assert.equal(parsed.compressed, f.compact.compressed) - }) - }) - - fixtures.invalid.compact.forEach(function(f) { - it('throws on ' + f.hex, function() { - var buffer = new Buffer(f.hex, 'hex') - - assert.throws(function() { - ecdsa.parseSigCompact(buffer) - }, new RegExp(f.exception)) - }) - }) - }) }) diff --git a/test/ecsignature.js b/test/ecsignature.js new file mode 100644 index 0000000..cf46987 --- /dev/null +++ b/test/ecsignature.js @@ -0,0 +1,82 @@ +var assert = require('assert') + +var BigInteger = require('bigi') +var ECSignature = require('../src/ecsignature') + +var fixtures = require('./fixtures/ecsignature.json') + +describe('ECSignature', function() { + describe('toCompact', function() { + fixtures.valid.forEach(function(f) { + it('encodes ' + f.compact.hex + ' correctly', function() { + var signature = new ECSignature( + new BigInteger(f.signature.r), + new BigInteger(f.signature.s) + ) + + var buffer = signature.toCompact(f.compact.i, f.compact.compressed) + assert.equal(buffer.toString('hex'), f.compact.hex) + }) + }) + }) + + describe('fromCompact', function() { + fixtures.valid.forEach(function(f) { + it('decodes ' + f.compact.hex + ' correctly', function() { + var buffer = new Buffer(f.compact.hex, 'hex') + var parsed = ECSignature.fromCompact(buffer) + + assert.equal(parsed.compressed, f.compact.compressed) + assert.equal(parsed.i, f.compact.i) + assert.equal(parsed.signature.r.toString(), f.signature.r) + assert.equal(parsed.signature.s.toString(), f.signature.s) + }) + }) + + fixtures.invalid.compact.forEach(function(f) { + it('throws on ' + f.hex, function() { + var buffer = new Buffer(f.hex, 'hex') + + assert.throws(function() { + ECSignature.fromCompact(buffer) + }, new RegExp(f.exception)) + }) + }) + }) + + describe('toDER', function() { + it('encodes a DER signature', function() { + fixtures.valid.forEach(function(f) { + var signature = new ECSignature( + new BigInteger(f.signature.r), + new BigInteger(f.signature.s) + ) + + var DER = signature.toDER() + assert.equal(DER.toString('hex'), f.DER) + }) + }) + }) + + describe('fromDER', function() { + it('decodes the correct signature', function() { + fixtures.valid.forEach(function(f) { + var buffer = new Buffer(f.DER, 'hex') + var signature = ECSignature.fromDER(buffer) + + assert.equal(signature.r.toString(), f.signature.r) + assert.equal(signature.s.toString(), f.signature.s) + }) + }) + + fixtures.invalid.DER.forEach(function(f) { + it('throws on ' + f.hex, function() { + var buffer = new Buffer(f.hex, 'hex') + + assert.throws(function() { + ECSignature.fromDER(buffer) + }, new RegExp(f.exception)) + }) + }) + }) +}) diff --git a/test/fixtures/ecdsa.json b/test/fixtures/ecdsa.json index c10d691..3f1421f 100644 --- a/test/fixtures/ecdsa.json +++ b/test/fixtures/ecdsa.json @@ -4,12 +4,7 @@ "d": "01", "k": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5", "message": "Everything should be made as simple as possible, but not simpler.", - "compact": { - "hex": "1f33a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c96f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262", - "compressed": true, - "i": 0 - }, - "DER": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262", + "i": 0, "signature": { "r": "23362334225185207751494092901091441011938859014081160902781146257181456271561", "s": "50433721247292933944369538617440297985091596895097604618403996029256432099938" @@ -19,12 +14,7 @@ "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "k": "9dc74cbfd383980fb4ae5d2680acddac9dac956dca65a28c80ac9c847c2374e4", "message": "Equations are more important to me, because politics is for the present, but an equation is something for eternity.", - "compact": { - "hex": "1b54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5", - "compressed": false, - "i": 0 - }, - "DER": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5", + "i": 0, "signature": { "r": "38341707918488238920692284707283974715538935465589664377561695343399725051885", "s": "3180566392414476763164587487324397066658063772201694230600609996154610926757" @@ -34,12 +24,7 @@ "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "k": "fd27071f01648ebbdd3e1cfbae48facc9fa97edc43bbbc9a7fdc28eae13296f5", "message": "Not only is the Universe stranger than we think, it is stranger than we can think.", - "compact": { - "hex": "1fff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd06fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283", - "compressed": true, - "i": 0 - }, - "DER": "3045022100ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd002206fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283", + "i": 0, "signature": { "r": "115464191557905790016094131873849783294273568009648050793030031933291767741904", "s": "50562520307781850052192542766631199590053690478900449960232079510155113443971" @@ -49,12 +34,7 @@ "d": "0000000000000000000000000000000000000000000000000000000000000001", "k": "f0cd2ba5fc7c183de589f6416220a36775a146740798756d8d949f7166dcc87f", "message": "How wonderful that we have met with a paradox. Now we have some hope of making progress.", - "compact": { - "hex": "1cc0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d375afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3", - "compressed": false, - "i": 1 - }, - "DER": "3045022100c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3022075afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3", + "i": 1, "signature": { "r": "87230998027579607140680851455601772643840468630989315269459846730712163783123", "s": "53231320085894623106179381504478252331065330583563809963303318469380290929875" @@ -64,12 +44,7 @@ "d": "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64", "k": "6bb4a594ad57c1aa22dbe991a9d8501daf4688bf50a4892ef21bd7c711afda97", "message": "Computer science is no more about computers than astronomy is about telescopes.", - "compact": { - "hex": "1f7186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d0de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6", - "compressed": true, - "i": 0 - }, - "DER": "304402207186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d02200de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6", + "i": 0, "signature": { "r": "51348483531757779992459563033975330355971795607481991320287437101831125115997", "s": "6277080015686056199074771961940657638578000617958603212944619747099038735862" @@ -79,12 +54,7 @@ "d": "00000000000000000000000000007246174ab1e92e9149c6e446fe194d072637", "k": "097b5c8ee22c3ea78a4d3635e0ff6fe85a1eb92ce317ded90b9e71aab2b861cb", "message": "...if you aren't, at any given time, scandalized by code you wrote five or even three years ago, you're not learning anywhere near enough", - "compact": { - "hex": "1cfbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda4870e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37", - "compressed": false, - "i": 1 - }, - "DER": "3045022100fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda48702200e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37", + "i": 1, "signature": { "r": "113979859486826658566290715281614250298918272782414232881639314569529560769671", "s": "6517071009538626957379450615706485096874328019806177698938278220732027419959" @@ -94,12 +64,7 @@ "d": "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3", "k": "19355c36c8cbcdfb2382e23b194b79f8c97bf650040fc7728dfbf6b39a97c25b", "message": "The question of whether computers can think is like the question of whether submarines can swim.", - "compact": { - "hex": "20cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf906ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef", - "compressed": true, - "i": 1 - }, - "DER": "3045022100cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9022006ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef", + "i": 1, "signature": { "r": "93122007060065279508564838030979550535085999589142852106617159184757394422777", "s": "3078539468410661027472930027406594684630312677495124015420811882501887769839" @@ -107,42 +72,6 @@ } ], "invalid": { - "compact": [ - { - "exception": "Invalid signature parameter", - "hex": "23987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e93791d7629795b62" - }, - { - "exception": "Invalid signature length", - "hex": "1c987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e93791d7629795b62000000" - }, - { - "exception": "Invalid signature length", - "hex": "1c987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e9379" - } - ], - "DER": [ - { - "exception": "Invalid sequence length", - "hex": "30ff0204ffffffff0204ffffffff" - }, - { - "exception": "Invalid sequence length", - "hex": "300c0304ffffffff0304ffffffff0000" - }, - { - "exception": "Expected a DER integer", - "hex": "300cff04ffffffff0204ffffffff" - }, - { - "exception": "Expected a DER integer \\(2\\)", - "hex": "300c0202ffffffff0204ffffffff" - }, - { - "exception": "Invalid DER encoding", - "hex": "300c0204ffffffff0202ffffffff" - } - ], "recoverPubKey": [ { "description": "Invalid r value (== 0)", diff --git a/test/fixtures/ecsignature.json b/test/fixtures/ecsignature.json new file mode 100644 index 0000000..8538356 --- /dev/null +++ b/test/fixtures/ecsignature.json @@ -0,0 +1,126 @@ +{ + "valid": [ + { + "compact": { + "hex": "1f33a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c96f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262", + "compressed": true, + "i": 0 + }, + "DER": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262", + "signature": { + "r": "23362334225185207751494092901091441011938859014081160902781146257181456271561", + "s": "50433721247292933944369538617440297985091596895097604618403996029256432099938" + } + }, + { + "compact": { + "hex": "1b54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5", + "compressed": false, + "i": 0 + }, + "DER": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5", + "signature": { + "r": "38341707918488238920692284707283974715538935465589664377561695343399725051885", + "s": "3180566392414476763164587487324397066658063772201694230600609996154610926757" + } + }, + { + "compact": { + "hex": "1fff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd06fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283", + "compressed": true, + "i": 0 + }, + "DER": "3045022100ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd002206fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283", + "signature": { + "r": "115464191557905790016094131873849783294273568009648050793030031933291767741904", + "s": "50562520307781850052192542766631199590053690478900449960232079510155113443971" + } + }, + { + "compact": { + "hex": "1cc0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d375afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3", + "compressed": false, + "i": 1 + }, + "DER": "3045022100c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3022075afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3", + "signature": { + "r": "87230998027579607140680851455601772643840468630989315269459846730712163783123", + "s": "53231320085894623106179381504478252331065330583563809963303318469380290929875" + } + }, + { + "compact": { + "hex": "1f7186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d0de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6", + "compressed": true, + "i": 0 + }, + "DER": "304402207186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d02200de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6", + "signature": { + "r": "51348483531757779992459563033975330355971795607481991320287437101831125115997", + "s": "6277080015686056199074771961940657638578000617958603212944619747099038735862" + } + }, + { + "compact": { + "hex": "1cfbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda4870e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37", + "compressed": false, + "i": 1 + }, + "DER": "3045022100fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda48702200e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37", + "signature": { + "r": "113979859486826658566290715281614250298918272782414232881639314569529560769671", + "s": "6517071009538626957379450615706485096874328019806177698938278220732027419959" + } + }, + { + "compact": { + "hex": "20cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf906ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef", + "compressed": true, + "i": 1 + }, + "DER": "3045022100cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9022006ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef", + "signature": { + "r": "93122007060065279508564838030979550535085999589142852106617159184757394422777", + "s": "3078539468410661027472930027406594684630312677495124015420811882501887769839" + } + } + ], + "invalid": { + "compact": [ + { + "exception": "Invalid signature parameter", + "hex": "23987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e93791d7629795b62" + }, + { + "exception": "Invalid signature length", + "hex": "1c987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e93791d7629795b62000000" + }, + { + "exception": "Invalid signature length", + "hex": "1c987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e9379" + } + ], + "DER": [ + { + "exception": "Invalid sequence length", + "hex": "30ff0204ffffffff0204ffffffff" + }, + { + "exception": "Invalid sequence length", + "hex": "300c0304ffffffff0304ffffffff0000" + }, + { + "exception": "Expected a DER integer", + "hex": "300cff04ffffffff0204ffffffff" + }, + { + "exception": "Expected a DER integer \\(2\\)", + "hex": "300c0202ffffffff0204ffffffff" + }, + { + "exception": "Invalid DER encoding", + "hex": "300c0204ffffffff0202ffffffff" + } + ] + } +}