Skip to content

Commit

Permalink
rm ECSignature, add script.signature instead
Browse files Browse the repository at this point in the history
  • Loading branch information
dcousens committed Apr 13, 2018
1 parent 93b815c commit 5350eb5
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 47 deletions.
6 changes: 4 additions & 2 deletions src/ecdsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ var typeforce = require('typeforce')
var types = require('./types')

var BigInteger = require('bigi')
var ECSignature = require('./ecsignature')

var ZERO = Buffer.alloc(1, 0)
var ONE = Buffer.alloc(1, 1)
Expand Down Expand Up @@ -102,7 +101,10 @@ function sign (hash, d) {
s = n.subtract(s)
}

return new ECSignature(r, s)
return {
r: r,
s: s
}
}

function verify (hash, signature, Q) {
Expand Down
1 change: 0 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ module.exports = {

Block: require('./block'),
ECPair: require('./ecpair'),
ECSignature: require('./ecsignature'),
HDNode: require('./hdnode'),
Transaction: require('./transaction'),
TransactionBuilder: require('./transaction_builder'),
Expand Down
1 change: 1 addition & 0 deletions src/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ module.exports = {
toStack: toStack,

number: require('./script_number'),
signature: require('./script_signature'),

isCanonicalPubKey: isCanonicalPubKey,
isCanonicalSignature: isCanonicalSignature,
Expand Down
58 changes: 58 additions & 0 deletions src/script_signature.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
var bip66 = require('bip66')
var BigInteger = require('bigi')
var typeforce = require('typeforce')
var types = require('./types')

// BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed)
function decode (buffer) {
var hashType = buffer.readUInt8(buffer.length - 1)
var hashTypeMod = hashType & ~0x80
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)

var decode = bip66.decode(buffer.slice(0, -1))

return {
signature: {
r: BigInteger.fromDERInteger(decode.r),
s: BigInteger.fromDERInteger(decode.s)
},
hashType: hashType
}
}

function toRSBuffer (signature) {
var r = signature.r.toBuffer(32)
var s = signature.s.toBuffer(32)
return Buffer.concat([r, s])
}

function fromRSBuffer (buffer) {
typeforce(types.BufferN(64), buffer)

var r = BigInteger.fromBuffer(buffer.slice(0, 32))
var s = BigInteger.fromBuffer(buffer.slice(32, 64))
return { r: r, s: s }
}

function encode (signature, hashType) {
var hashTypeMod = hashType & ~0x80
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)

var hashTypeBuffer = new Buffer(1)
hashTypeBuffer.writeUInt8(hashType, 0)

var r = new Buffer(signature.r.toDERInteger())
var s = new Buffer(signature.s.toDERInteger())

return Buffer.concat([
bip66.encode(r, s),
hashTypeBuffer
])
}

module.exports = {
toRSBuffer,
fromRSBuffer,
decode: decode,
encode: encode
}
7 changes: 3 additions & 4 deletions src/transaction_builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ var SIGNABLE = [btemplates.types.P2PKH, btemplates.types.P2PK, btemplates.types.
var P2SH = SIGNABLE.concat([btemplates.types.P2WPKH, btemplates.types.P2WSH])

var ECPair = require('./ecpair')
var ECSignature = require('./ecsignature')
var Transaction = require('./transaction')

function supportedType (type) {
Expand Down Expand Up @@ -190,7 +189,7 @@ function fixMultisigOrder (input, transaction, vin) {
if (!signature) return false

// TODO: avoid O(n) hashForSignature
var parsed = ECSignature.parseScriptSignature(signature)
var parsed = bscript.signature.decode(signature)
var hash = transaction.hashForSignature(vin, input.redeemScript, parsed.hashType)

// skip if signature does not match pubKey
Expand Down Expand Up @@ -716,9 +715,9 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy
)) throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH')

var signature = keyPair.sign(signatureHash)
if (Buffer.isBuffer(signature)) signature = ECSignature.fromRSBuffer(signature)
if (Buffer.isBuffer(signature)) signature = bscript.signature.fromRSBuffer(signature)

input.signatures[i] = signature.toScriptSignature(hashType)
input.signatures[i] = bscript.signature.encode(signature, hashType)
return true
})

Expand Down
9 changes: 5 additions & 4 deletions test/bitcoin.core.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,14 @@ describe('Bitcoin-core', function () {
})
})

describe('ECSignature.parseScriptSignature', function () {
describe('script.signature.decode', function () {
sigCanonical.forEach(function (hex) {
var buffer = Buffer.from(hex, 'hex')

it('can parse ' + hex, function () {
var parsed = bitcoin.ECSignature.parseScriptSignature(buffer)
var actual = parsed.signature.toScriptSignature(parsed.hashType)
var parsed = bitcoin.script.signature.decode(buffer)
var actual = bitcoin.script.signature.encode(parsed.signature, parsed.hashType)

assert.strictEqual(actual.toString('hex'), hex)
})
})
Expand All @@ -218,7 +219,7 @@ describe('Bitcoin-core', function () {

it('throws on ' + description, function () {
assert.throws(function () {
bitcoin.ECSignature.parseScriptSignature(buffer)
bitcoin.script.signature.decode(buffer)
}, /Expected DER (integer|sequence)|(R|S) value (excessively padded|is negative)|(R|S|DER sequence) length is (zero|too short|too long|invalid)|Invalid hashType/)
})
})
Expand Down
31 changes: 19 additions & 12 deletions test/ecdsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,31 @@

var assert = require('assert')
var bcrypto = require('../src/crypto')
var bscript = require('../src/script')
var ecdsa = require('../src/ecdsa')
var hoodwink = require('hoodwink')

var BigInteger = require('bigi')
var ECSignature = require('../src/ecsignature')

var curve = ecdsa.__curve

var fixtures = require('./fixtures/ecdsa.json')

describe('ecdsa', function () {
function fromRaw (signature) {
return {
r: new BigInteger(signature.r, 16),
s: new BigInteger(signature.s, 16)
}
}

function toRaw (signature) {
return {
r: signature.r.toHex(),
s: signature.s.toHex()
}
}

describe('deterministicGenerateK', function () {
function checkSig () {
return true
Expand Down Expand Up @@ -80,9 +94,9 @@ describe('ecdsa', function () {
it('produces a deterministic signature for "' + f.message + '"', function () {
var d = BigInteger.fromHex(f.d)
var hash = bcrypto.sha256(f.message)
var signature = ecdsa.sign(hash, d).toDER()
var signature = ecdsa.sign(hash, d)

assert.strictEqual(signature.toString('hex'), f.signature)
assert.deepEqual(toRaw(signature), f.signature)
})
})

Expand All @@ -101,7 +115,7 @@ describe('ecdsa', function () {
it('verifies a valid signature for "' + f.message + '"', function () {
var d = BigInteger.fromHex(f.d)
var H = bcrypto.sha256(f.message)
var signature = ECSignature.fromDER(Buffer.from(f.signature, 'hex'))
var signature = fromRaw(f.signature)
var Q = curve.G.multiply(d)

assert(ecdsa.verify(H, signature, Q))
Expand All @@ -112,14 +126,7 @@ describe('ecdsa', function () {
it('fails to verify with ' + f.description, function () {
var H = bcrypto.sha256(f.message)
var d = BigInteger.fromHex(f.d)

var signature
if (f.signature) {
signature = ECSignature.fromDER(Buffer.from(f.signature, 'hex'))
} else if (f.signatureRaw) {
signature = new ECSignature(new BigInteger(f.signatureRaw.r, 16), new BigInteger(f.signatureRaw.s, 16))
}

var signature = fromRaw(f.signature)
var Q = curve.G.multiply(d)

assert.strictEqual(ecdsa.verify(H, signature, Q), false)
Expand Down
61 changes: 39 additions & 22 deletions test/fixtures/ecdsa.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,64 @@
"d": "01",
"k": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5",
"message": "Everything should be made as simple as possible, but not simpler.",
"i": 0,
"signature": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262"
"signature": {
"r": "33a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c9",
"s": "6f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262"
}
},
{
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"k": "9dc74cbfd383980fb4ae5d2680acddac9dac956dca65a28c80ac9c847c2374e4",
"message": "Equations are more important to me, because politics is for the present, but an equation is something for eternity.",
"i": 0,
"signature": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
"signature": {
"r": "54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed",
"s": "07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
}
},
{
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"k": "fd27071f01648ebbdd3e1cfbae48facc9fa97edc43bbbc9a7fdc28eae13296f5",
"message": "Not only is the Universe stranger than we think, it is stranger than we can think.",
"i": 0,
"signature": "3045022100ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd002206fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283"
"signature": {
"r": "ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd0",
"s": "6fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283"
}
},
{
"d": "0000000000000000000000000000000000000000000000000000000000000001",
"k": "f0cd2ba5fc7c183de589f6416220a36775a146740798756d8d949f7166dcc87f",
"message": "How wonderful that we have met with a paradox. Now we have some hope of making progress.",
"i": 1,
"signature": "3045022100c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3022075afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3"
"signature": {
"r": "c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3",
"s": "75afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3"
}
},
{
"d": "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64",
"k": "6bb4a594ad57c1aa22dbe991a9d8501daf4688bf50a4892ef21bd7c711afda97",
"message": "Computer science is no more about computers than astronomy is about telescopes.",
"i": 0,
"signature": "304402207186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d02200de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6"
"signature": {
"r": "7186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d",
"s": "0de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6"
}
},
{
"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",
"i": 1,
"signature": "3045022100fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda48702200e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37"
"signature": {
"r": "fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda487",
"s": "0e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37"
}
},
{
"d": "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3",
"k": "19355c36c8cbcdfb2382e23b194b79f8c97bf650040fc7728dfbf6b39a97c25b",
"message": "The question of whether computers can think is like the question of whether submarines can swim.",
"i": 1,
"signature": "3045022100cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9022006ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef"
"signature": {
"r": "cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9",
"s": "06ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef"
}
}
],
"rfc6979": [
Expand Down Expand Up @@ -130,13 +144,16 @@
"description": "The wrong signature",
"d": "01",
"message": "foo",
"signature": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
"signature": {
"r": "54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed",
"s": "07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
}
},
{
"description": "Invalid r value (< 0)",
"d": "01",
"message": "foo",
"signatureRaw": {
"signature": {
"r": "-01",
"s": "02"
}
Expand All @@ -145,7 +162,7 @@
"description": "Invalid r value (== 0)",
"d": "01",
"message": "foo",
"signatureRaw": {
"signature": {
"r": "00",
"s": "02"
}
Expand All @@ -154,7 +171,7 @@
"description": "Invalid r value (>= n)",
"d": "01",
"message": "foo",
"signatureRaw": {
"signature": {
"r": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
"s": "02"
}
Expand All @@ -163,7 +180,7 @@
"description": "Invalid s value (< 0)",
"d": "01",
"message": "foo",
"signatureRaw": {
"signature": {
"r": "02",
"s": "-01"
}
Expand All @@ -172,7 +189,7 @@
"description": "Invalid s value (== 0)",
"d": "01",
"message": "foo",
"signatureRaw": {
"signature": {
"r": "02",
"s": "00"
}
Expand All @@ -181,7 +198,7 @@
"description": "Invalid s value (>= n)",
"d": "01",
"message": "foo",
"signatureRaw": {
"signature": {
"r": "02",
"s": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
}
Expand All @@ -190,7 +207,7 @@
"description": "Invalid r, s values (r = s = -n)",
"d": "01",
"message": "foo",
"signatureRaw": {
"signature": {
"r": "-fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
"s": "-fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
}
Expand Down
Loading

0 comments on commit 5350eb5

Please sign in to comment.